-
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
Support for Nested Relationships for the Json Adapter #1114
Support for Nested Relationships for the Json Adapter #1114
Conversation
bef5e07
to
db5d174
Compare
c75fbe3
to
05ec32a
Compare
@@ -47,6 +26,151 @@ def fragment_cache(cached_hash, non_cached_hash) | |||
Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash) | |||
end | |||
|
|||
private |
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.
👍
end | ||
end | ||
|
||
def resource_object_for(serializer) |
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.
Nice abstraction! 👍
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.
thanks!
…nships to nested_associations_to_include
@first_comment.author = @author | ||
@second_comment.author = @author | ||
|
||
serializer = ComplexNestedAuthorSerializer.new(@author) |
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.
loving the name
# have the include array normalized | ||
nested_associations = include_array_to_hash(nested_associations) | ||
|
||
included_associations = if nested_associations.present? |
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.
so nested_associations
should be an normalized array with the nested objects you need.
Eg.
BlogSerializer
with has_many :posts include: [:author]
so nested_associations
will tell you that you need author
but inside this if
you check if it is included iinside serializer.associations
with .select
. But serializer.associations will have only posts
.
Initially I thought this was to check if it's an already rendered relationship and avoid render it again. but it seems it is used here to loop the associations.
What I presume is the the code inside this if might never be executed unless you have something like (probably):
Eg.
BlogSerializer
with has_many :posts include: [:author.posts]
then you will find the posts
inside nested_associations
as a member of 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.
The if body actually decides what nested association to render.
Cause, lets say a post has a ton of associations, but you only want the author.
by the time you get to rendering the posts, [:author]
will be passed in as nested_associations
and the select filters for :author
among all of a post's associations.
(The tests also cover this scenario)
# it would normally be silly to have this in production code, cause a post's | ||
# author in this case is always going to be your root object | ||
has_many :posts, include: [:author, comments: [:author]] | ||
end |
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.
Would be nice to cover scenarios using multiple association declarations as well 👍
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'll add a test for that real quick, just to be sure
We made a nice and big review here, this is complex but solid, something we aim to have on 0.10.x. |
hashes = include_array.select{|a| a.is_a?(Hash)} | ||
non_hashes = include_array - hashes | ||
|
||
hashes += non_hashes.map{ |association_name| { association_name => [] } } |
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.
better to mutate hashes
than generate a new object, I 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.
how come?
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 seems more like a function than a (private) property of the JSON Adapter.. What would you think about adding a
module ActiveModel::Serializer::Utils
module_function
def include_array_to_hash(include_array)
# still don't trust input
# but this also allows
# include: :author syntax
include_array = Array[*include_array].compact
result = {}
hashes = include_array.select{|a| a.is_a?(Hash)}
non_hashes = include_array - hashes
hashes += non_hashes.map{ |association_name| { association_name => [] } }
# now merge all the hashes
hashes.each{|hash| result.merge!(hash) }
result
end
end
and then Utils.include_array_to_hash
or mix it in
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 like that. Calling it as a class metho would be my preference.
Just waiting to merge #1017 before going back to this |
woo! |
…izers into nested-relationships Conflicts: lib/active_model/serializer/adapter/json.rb
…sociation declaration in the JSON adapter initial refactor to make way for easy feature adding refactored a bit more, and matched some method names to that of json_api rename add_relationship methods to be less awkward tests added all tests tpass remove binding.pry require fixed app warnings removed unused method changed restrict_to to nested_associations and changed nested_relationships to nested_associations_to_include removed unneeded parameter from add_resource_relationships simplify key check added another test, showing multiple relationship serializers refactored include_array_to_hash to a utils module - this also simplified the test for it. yay fixed merge conflicts
Conflicts: test/action_controller/serialization_test.rb
Well, I accidentally committed a merge instead of a rebase. tried to checkout my last commit, and rebase that then force push to this branch... didn't work out so well. haha |
Closed in favor of #1124 (Cleaner git history - but same changes) |
👍 |
This PR is based off of #1111, cause I needed the refactoring.
Discussion of idea here: #1113
Basically:
resulting json may look like:
See the included tests for more examples.