Skip to content

Conversation

@christophersansone
Copy link
Contributor

  • Fixes Problems with the validation of the include option #41. Originally, include would be validated up front every time a serializer is instantiated, which (a) takes time, and (b) is limited to only validating static relationships, so polymorphic, object blocks, serializer blocks, etc. could not be validated. Now, instead, it will simply assume that include is valid, attempt the serialization, and fail if the relationship does not exist.

  • Per @stas's comment in Problems with the validation of the include option #41, the validation raises a custom exception instead of a plain old ArgumentError. I created an errors.rb file so that we can have a common place to define custom exceptions, like most gems do.

  • Improved the syntax of include to be much more flexible. Now you can specify strings, symbols, arrays, and hashes (for nested relationships). Dot notation still works, and in fact is improved because now you don't need to specify the parents separately, e.g. [ :actors, :'actors.agency' ]. Now you can simply say 'actors.agency', and it implicitly includes actors too. But best of all, you can now write this as { actors: [ :agency ] }, or simply { actors: :agency }. In general, this should also be a performance improvement, because the code originally parsed include and split strings during each iteration. Now it parses it once up front, builds a nice relationship tree, and passes the proper branch of the tree to each relationship during serialization.

@stas
Copy link
Collaborator

stas commented Feb 14, 2020

@christophersansone thank you for working on this.

I have only one concern here, please help me understand why do we need to support 3 types of syntaxes for include? I think this is confusing and unnecessary, considering the fact that spec suggests it's always a comma-separated list of values. I'd like us to keep things the way they are and as simple as possible (not to mention that the hash syntax for a single include member is weird include: {rel: {}}).

Code-wise, may I suggest two things please:

@christophersansone
Copy link
Contributor Author

@stas Thanks for the quick feedback.

...considering the fact that spec suggests it's always a comma-separated list of values...

Sorry, where is this? I added a whole new file of specs to define the behavior, and I did not see anything in the Readme. I'd be happy to adjust wherever that is.

... hash syntax for a single include member is weird include: {rel: {}} ...

I don't think people will do it that way. Just opt for a different syntax, most simply include: :rel or include: [:rel]. If you have other relationships that are nested, do something like include: [:rel, { foo: :bar }].

... why do we need to support 3 types of syntaxes for include?

The existing format is really not very Rubyesque. I don't know of any other library that uses dot notation strings to define nesting. It is also extremely cumbersome and error prone when you are including several relationships several levels deep.

Two examples of heavily used Ruby methods that use similar syntax to what I'm proposing is ActiveModel joins and includes, and also ActionController's strong parameters. The syntax will be familiar to all who use these. In fact, I would think that in most cases where people are using ActiveModel and FastJSONAPI, their ActiveModel includes will look much like their FastJSONAPI include. These methods have similar flexibility as well: define strings, symbols, arrays, and / or hashes. But not dot notation. 😄 ActiveModel Serializers also uses a similar format for defining include as well.

Of course, we need to keep the dot notation syntax around for backward compatibility, so like it or not, it's not going anywhere. I much prefer the new syntax and think it's more intuitive for the Ruby community.

@stas
Copy link
Collaborator

stas commented Feb 14, 2020

Sorry, where is this? I added a whole new file of specs to define the behavior, and I did not see anything in the Readme. I'd be happy to adjust wherever that is.

@christophersansone I'm looking at this https://jsonapi.org/format/#fetching-includes

Sorry, I'm just trying to keep things as close as possible to what the spec suggests.

@christophersansone
Copy link
Contributor Author

@stas Ahh, okay. Well, it also says it needs to be a comma-separated, dot notated list, all in one string, e.g. foo,bar,bar.baz. AFAIK this library never supported comma separation: it expects an array of dot-notated strings. We can do that if needed though!

I think the main difference here is that the json:api spec is (rightfully) language agnostic. But this library lives in Ruby and is used by Ruby developers. Sometimes, for some projects, the list of includes will come from the include parameter passed from the client. Other times, it will be the Ruby developer deciding what gets included, so let's give them a syntax that is familiar to them.

@stas
Copy link
Collaborator

stas commented Feb 14, 2020

@christophersansone let's just keep the API interface we already have in place. I can't imagine folks parsing a query string of comma-separated dot-notation value into a hash, so we're definitely not going in the right direction by supporting that. The most common use-case here is that one sends a query param like in the spec examples, at most that is split into a list of values and fed to fast_jsonapi. So maintaining what we have for now, should be more than enough.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problems with the validation of the include option

2 participants