Skip to content
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

Serialize nested includes #152

Merged
merged 19 commits into from
May 11, 2018
Merged

Conversation

jshow
Copy link
Contributor

@jshow jshow commented Apr 3, 2018

  • Dish off to associated serializers when required

includes syntax is:

      options[:include] = [:actors, :'actors.agency']
      serializable_hash = MovieSerializer.new([movie], options).serializable_hash

@thommahoney
Copy link

This functionality is a much-desired addition to this library. Without it, I cannot fully adopt this gem for my needs. Could we get some eyes on this PR? Even if the implementation isn't exactly ideal, I personally think the interface is appropriate to support in the long term.

The other proposed API in #47 was the following:

options[:include] = [ actors: [:agency] ]

I prefer the API in this PR as it more closely maps to the JSON-API specification:

options[:include] = [:actors, :'actors.agency']

The former would require splitting the include query parameter on comma and then building a hash with arrays of symbols as values. The latter only requires splitting on comma and mapping :to_sym:

options[:include] = params[:include].split(',').map(&:to_sym)

Either way, it'd be nice for fast_jsonapi to provide a method for converting the query parameter into the options hash value based on the relationships in the serializers but I don't see that as necessary for this PR to move forward.

if remaining_items
serializer_records = serializer.get_included_records(inc_obj, remaining_items, known_included_objects)
included_records << serializer_records unless serializer_records.empty?
end
Copy link

@nathanstitt nathanstitt Apr 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the << operator should be replaced by .concat. Since serializer_records is an array, this creates a nested array when you really want to append the contents of serializer_records to the included_records array.

I tested the change and was seeing the nested included records being added as an array to the existing included property. I also suspect that's why the specs failed.

    included_records.concat(serializer_records) unless serializer_records.empty?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you @nathanstitt , both the implementation and the spec were wrong - both addressed. cheers

@jshow jshow changed the base branch from master to dev April 5, 2018 20:09
item_to_serialize = items.last

items.each do |item|
next unless relationships_to_serialize[item]
Copy link

@yalesov yalesov Apr 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/LifeTales/fast_jsonapi/blob/49e7e86e93c61fa5cf34278144378c8640d9f079/lib/fast_jsonapi/object_serializer.rb#L154-L155

relationships_to_serialize might be nil, throwing undefined method '[]' for nil:NilClass; need to catch that too.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made corresponding PR for this at LifeTales#1

@gschorkopf
Copy link

Can I help in rebasing anything to resolve 👇 merge conflict?

@jshow
Copy link
Contributor Author

jshow commented Apr 10, 2018

much appreciated @gschorkopf

@gschorkopf
Copy link

gschorkopf commented Apr 10, 2018

Just a heads up: I rebased locally and was ready to push, but got several errors in the speed test section of the suite. Along the lines of:

FastJsonapi::ObjectSerializer when comparing with AMS 0.10.x should serialize 1 records atleast 25 times faster than AMS
expected: >= 25
got:    22.57446706623082

If any of y'all have time today to rebase and investigate, that'd be swell.

@jshow
Copy link
Contributor Author

jshow commented Apr 10, 2018

thanks @gschorkopf - I get those performance related failures pulling master

@llenodo
Copy link

llenodo commented Apr 13, 2018

Anything blocking this PR? Would love to use this added functionality ASAP

@thommahoney
Copy link

@jshow could you resolve the conflicts on this branch at least? Unsure which of the maintainers to ping to get this out but the merge conflicts will block that progress.

@jshow jshow force-pushed the serialize_nested_includes branch from 049f8d9 to 341bf9b Compare April 17, 2018 20:20
@jshow
Copy link
Contributor Author

jshow commented Apr 17, 2018

@thommahoney , rebased against dev, we're gold now

@jshow
Copy link
Contributor Author

jshow commented Apr 17, 2018

@nathanstitt , wdyt ?

@nathanstitt
Copy link

@jshow looks good to me - I've been tracking the branch in a new app I'm spiking and it seems to be working well.

@gabrielmm1234
Copy link

When is it going to be merged?

@ankit8898 ankit8898 added the enhancement New feature or request label Apr 20, 2018
@mhluska
Copy link
Contributor

mhluska commented Apr 22, 2018

Does this currently work with polymorphic associations? include: [:'order_items.item'] throws NameError (uninitialized constant ItemSerializer) for me. Not sure if related.

Copy link
Collaborator

@shishirmk shishirmk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general i like the way nested includes are specified.
However we need to make the code bit more readable and some more tests covering more corner cases. We would need to add some documentation as well

@@ -235,6 +237,25 @@ def fetch_polymorphic_option(options)
return option if option.respond_to? :keys
{}
end

def get_serializer(item)
unless item.to_s.include?('.')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic seems very similar for both parts of this method. Is there anyway we can combine them and make it more concise?

…ludes

Conflicts:
	lib/fast_jsonapi/serialization_core.rb
	spec/shared/contexts/movie_context.rb
@jshow
Copy link
Contributor Author

jshow commented May 8, 2018

@shishirmk , I've simplified the validates of includes options, plus dry'ed up the parsing of nested includes

is this providing the kind of clarity you were looking for ? If not, please provide more specific direction

I'll work on the README once we've settled the code

This is a long running branch, getting tough to deal with merge conflicts, I'd appreciate a quick cycle so we can get this into dev. thanks

@shishirmk
Copy link
Collaborator

@jshow will take a look today and try to make this a quicker development cycle.

@@ -234,6 +224,20 @@ def fetch_polymorphic_option(options)
return option if option.respond_to? :keys
{}
end

def validate_includes!(includes)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method looks good.

@@ -30,6 +30,30 @@
expect(serializable_hash[:included]).to be nil
end

it 'returns correct nested includes when serializable_hash is called' do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add more tests

  • test a has many
  • test a has_one
  • test a multi level case for example 'actors.agency.adresses'
  • we should test this with a polymorphic relationship
  • we should probably also test it with a relationship block Enable to use block to define relationship #195

@shishirmk
Copy link
Collaborator

shishirmk commented May 9, 2018

@jshow Thank you for working on this. the code looks good. Just need to add more tests and as you mentioned we need to add some documentation

@jshow
Copy link
Contributor Author

jshow commented May 9, 2018

@shishirmk , added some tests and found a bug with has_one - it was treated like a belongs_to - and tests to support that bad assumption - probably should be a separate PR, but couldn't move forward here without it being fixed, so it's all here

in addition

  • test a has many - done
  • test a has_one - done (with the provisor above)
  • test a multi level case for example 'actors.agency.adresses' - done
  • we should test this with a polymorphic relationship - this test is failing, what is the expected result, there aren't any tests that I can based the expected behaviour on - https://github.com/Netflix/fast_jsonapi/pull/152/files#diff-70daca4f50c5b49e4a8e037801a4c455R202
  • we should probably also test it with a relationship block #195 - not attempted yet

This has turned in a monstrous effort - specific comments to help bring this to the finish line are appreciated

@shishirmk
Copy link
Collaborator

shishirmk commented May 10, 2018

@jshow It's a lot of code changes. Thank you for getting this feature so far. I can take care of the remaining 2 tests in a another pull request. It would be great if you can document an example of how to use this feature. Also please resolve the conflicts so that i can merge it in.

@jshow
Copy link
Contributor Author

jshow commented May 10, 2018

Thanks for your support @shishirmk. It's all yours!

Once this makes it to dev, I'll get the associated #161 ready

@@ -146,7 +172,11 @@ def fetch_id(record, relationship, params)
return object.id
end

record.public_send(relationship[:id_method_name])
if relationship[:relationship_type] == :has_one
record.public_send(relationship[:object_method_name])&.id
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is causing a syntax error.

@shishirmk shishirmk merged commit 3ebf349 into Netflix:dev May 11, 2018
@jshow
Copy link
Contributor Author

jshow commented May 31, 2018

@shishirmk , can you explain to me why the last 2 PRs I worked on (this on and #161 ) , which were both merged to 1.2 (thank you, using master in production now), the commits are not attributed to me ?

I've worked hard for this project, partially for my personal benefit, and not being noted as a contributor, is demoralizing

@shishirmk
Copy link
Collaborator

@jshow taking a look.

@shishirmk
Copy link
Collaborator

@jshow It looks like it happened because of a squash merge. I didn't realize that it wouldn't automatically add all the authors in a squash merge. I have added you as a co-author by amending the comment. 8611ea6

Planning to add others that have contributed to 1.2 as well. Thank you for bringing this to my attention

@jshow
Copy link
Contributor Author

jshow commented Jun 1, 2018

thanks @shishirmk , cheers 🍻

@gadimbaylisahil
Copy link

Hi guys. Thanks for the feature. However, adding options[:include] = [:user, :'user.first_name'] Still renders the full json for the user object instead of just first name as attribute. Is it desired behaviour? I think something wrong here

@thommahoney
Copy link

@gadimbaylisahil have a look at #63 or #254 for that functionality

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.