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

Create NestedJson adapter. #1073

Closed
wants to merge 4 commits into from

Conversation

kayhide
Copy link

@kayhide kayhide commented Aug 21, 2015

I needed an adapter to serialize models with multi-depth relations for my project.
So I wrote it.

I think this might be helpful for some people.

@joaomdmoura
Copy link
Member

wow! Didn't reviewed it yet, but this is awesome, I'm definitely interest on this. I'll check tonight probably.

@kayhide
Copy link
Author

kayhide commented Aug 23, 2015

Hi,
I have checked the discussion on #921.

This adapter raises an error if nesting is too deep, typically in case of circular relations.
I think this is a desirable behavior for many cases.

If you want to change the limit depth, you can do it just giving an argument limit_depth: xx to the adapter, or setting default value NestedJson.default_limit_depth = xx.

cattr_accessor :default_limit_depth
@@default_limit_depth = 5

def serializable_hash options = {}
Copy link
Member

Choose a reason for hiding this comment

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

Yikes, it's a pretty big smell in the Json serializer that we're subclassing it but completely overriding this method, where everything important happens

also, might this belong in the Adapter superclass? It looks on first inspection like it would apply to the JsonApi adapter as well, no?

Copy link
Author

Choose a reason for hiding this comment

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

That is for #fragment_cache.

The way we cache fragmentation is exactly the same to Adapter::Json ( like Adapter::FlattenJson as well).
And Adapter::JsonApi caches differently.

@bf4
Copy link
Member

bf4 commented Aug 24, 2015

Thanks!

@joaomdmoura
Copy link
Member

Hey, sorry for taking so long, was really busy, now I stopped to check it our for real.
First of all tks @kayhide and @bf4 for your hard work. I really appreciate this.

I know that you needed multi-depth relations and make your own adapter was the fastest way, but IMO the best scenario would be to find a way to add it to json + flatten-json existing adapters. What are your thoughts about it? 😄

@kayhide
Copy link
Author

kayhide commented Aug 26, 2015

@joaomdmoura I agree with you.

OK, I will add these functionalities on this adaptor.

  • taking care of root
  • adding an option to trim off deep associations not to raise an error

After covering these, I think we can replace the existing json, flatten-json adapaters.

@kayhide kayhide force-pushed the nested_json_adapter branch from 7cf7d55 to 33c0300 Compare August 26, 2015 18:24
@kayhide
Copy link
Author

kayhide commented Aug 26, 2015

Hi, I updated the adapter and replaced existing Json/FlattenJson adapter.

This adapter accepts options:
limit_depth limits the depth of associations.

check_depth_strategy defines the behavior when nesting is too deep.
if :fail is set, it raises an error.
if :trim is set, it ignores deeper associations.

Setting limit_depth = 1 and check_depth_strategy = :trim makes its behavior just the same to the original Json/FlattenJson adapter.

And default values are available setting like:

Adapter::Json.default_limit_depth = 5
Adapter::Json.default_check_depth_strategy = :fail

For now, I set default values to follow original adapters behavior, and made them to pass all the existing tests untouched.
But I think people want it to handle nested associations to some depth as a default.

To do so, we need to fix the default values and rewrite the relevant tests.

@johnnagro johnnagro mentioned this pull request Aug 27, 2015
@bryanrite
Copy link

I really like this approach, defining all appropriate associations in each serializer and then being able to limit the depth in the controller is perfect.

@bryanrite
Copy link

One bug I noticed will trying out this branch, is that attributes with the name name cause an error now. For example, if the Comment model had a "name" attribute and you were serializing it like:

def Api::V1::CommentSerializer < ActiveModel::Serializer
  attribute :id
  attribute :name
end

you get:

undefined method `name' for #<Api::V1::CommentSerializer:0x007fdec7a23408>`

This is fixed by defining a method:

def name
  object.name
end

This is the only attribute it happens on that I have found so far.

@bryanrite
Copy link

And +1 for supporting a limit_depth of 0.

@kayhide
Copy link
Author

kayhide commented Aug 28, 2015

@bryanrite hi, thanks for your support :)

attributes with the name name cause an error

You can try attributes not attribute.
It's plural not singular.
Those are different methods.

As I read the code, singular version is for the case when the key and the accessor method are not the same.

@beauby
Copy link
Contributor

beauby commented Aug 28, 2015

The error is related to #1094.

@kayhide
Copy link
Author

kayhide commented Aug 28, 2015

Updated to support limitless depth.
Giving check_depth_strategy = :pass makes it go deep without any limit.
In this case the limit_depth value is ignored.

@kayhide
Copy link
Author

kayhide commented Aug 28, 2015

@beauby ah, right. thanks for the comment.

def fragment_cache(cached_hash, non_cached_hash)
Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
def too_deep? depth
if depth > @limit_depth
Copy link
Member

Choose a reason for hiding this comment

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

nice!

@NullVoxPopuli
Copy link
Contributor

closed in favor of #1127 and #1158
deep relationships are now managed via the include option passed in to the adapter

example:

render json: @posts, include: [:author, comments: author]

or

render json: @posts, include: 'author,comments.author'

@beauby beauby reopened this Sep 21, 2015
@beauby beauby closed this Sep 21, 2015
@beauby
Copy link
Contributor

beauby commented Sep 21, 2015

Moreover, the "depth strategy" is available via wildcards:

render json: @posts, include: '*.*.*'

This would include all nested relationships 3 levels down.

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

Successfully merging this pull request may close these issues.

6 participants