-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for wildcards in nested includes #1158
Conversation
f0bf341
to
883a684
Compare
@@ -119,10 +119,26 @@ def relationships_for(serializer) | |||
Hash[serializer.associations.map { |association| [association.key, { data: relationship_value_for(association.serializer, association.options) }] }] | |||
end | |||
|
|||
def expand_includes(includes, associations) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you write some yardoc about what this method does, and some example inputs and outputs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do!
Now also works with (Flatten)Json adapters. |
5d62e82
to
379c800
Compare
# and corresponding inclusion hashes. | ||
# @param [Hash] includes | ||
# @return [Array] an array of pairs [association, include_hash] for matching associations | ||
def expand_includes(includes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this format be different from the other format?
I'd prefer it to be the same, hash of hashes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one has a different purpose. I'm not happy with the name of this method, because what it really does is lookup each included association and returns the corresponding Association
and include hash. It just happens to expand stuff because at this stage we can't avoid it anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having this function just return a hash would force an other lookup of the associations down the road.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotchya
association.options[:virtual_value] | ||
elsif association.serializer && association.serializer.object | ||
FlattenJson.new(association.serializer, | ||
association.options.merge(include: assoc_includes)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line gives a rubocop warning about aligning method parameters that span multiple lines, although I believe the indentation is right here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have the first param on the next line, indented two spaces from the start of the F?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to https://github.com/bbatsov/ruby-style-guide#no-double-indent it should be ok like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be a bug in rubocop. I don't think it validates itself against the style guide and diverges at times
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but there's definitley too much going on in that block
52e5433
to
0de720d
Compare
@@ -2,6 +2,11 @@ module ActiveModel | |||
class Serializer | |||
module Adapter | |||
class Attributes < Base | |||
def initialize(serializer, options = {}) | |||
super | |||
@include_tree = ActiveModel::Serializer::IncludeTree.from_include_args(options[:include] || '*') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By default, include all the toplevel specified association (current behavior).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should the default value be move to the method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because we want the flexibility to have different default values per adapter. For instance, the JsonApi adapter defaults to none (since the relationship objects themselves will be serialized anyways, we don't want to enforce the related resources to be included in the answer unless specified by the user).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be in the initializer? Does it need to be eager evaluated? Also, you could
def initialize(*)
super
# use whatever the super method did
which is more resistant to changes in method signature or whatever
# | ||
# @param [String] included | ||
# @return [IncludeTree] | ||
# |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yay documentation!!!
but I think @return
is supposed to be the last line of the comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, there are many places in the current code base where the format is as above. I don't mind changing it, once we make a consistent choice for the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Long class << self
blocks are hard to read. Better to just use def self.method_name
.
I only did it in Adapter because I was class << Adapter
which is easier to read than def Adapter.whatever
and a little less surprising, but also I was intending to get rid of it eventually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to agree, although it's a pattern that is wildly used within rails. What do you think? I don't mind changing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer def self.method_name
unless you feel it's clearer or better otherwise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, updating immediately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, some of these styles will need to be autocorrected if we merge #1183
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think Helper
is a good name, but I wanted to just get the idea across :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I thought of Parsing
instead, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or Transformation.. but since it's internal so far, I'm not too concerned
I think this PR would benefit from including documentation of usage as well as caveats. I see this feature as a major bug report attractor, so would be great to just point to docs which describe what it can't be guaranteed to do well, or performantly. |
My intent was to build it first for internal usage (the wildcards themselves make the nested serializers much easier to write), and document it in a subsequent PR. |
@beauby Ok with me if you're doing it in steps like that. I haven't had the issue this PR is solving, so I'm not a 'domain' expert on what's best for AMS in this regard |
c396b0f
to
b6013c7
Compare
@@ -1,11 +1,11 @@ | |||
require 'thread_safe' | |||
require 'active_model/serializer/adapter' | |||
require 'active_model/serializer/array_serializer' | |||
require 'active_model/serializer/include_tree' | |||
require 'active_model/serializer/associations' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has to be before associations
, because we use it in there.
f9ee95a
to
53d780b
Compare
when @hash.key?(:**) | ||
self.class.new(:** => {}) | ||
else | ||
nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@beauby You're saying Rubocop didn't like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
53d780b
to
ac06013
Compare
Add support for wildcards in nested includes
Nice! 👍 |
Adds support for the following:
Note that the wildcard (
*
) only expands one level, so you can chain them if you want more and keep control over the depth of the inclusion ('comments.*.*'
for instance), or you can specify a double wildcard (**
) if you want infinite expansion.