-
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
Provide a clear way to include nested associations and fields #1849
Comments
Some thoughts: re: 1: the render include should for sure have the final say in what gets included. But with default include setups, how do specify that we don't want something (like if we're aggregating things for a large amount of data)? if using a render include means that default includes are ignored, I think that traversing the tree of default includes would be viable. re: 2: class PostSerializer < AM::S
default_include do |object, serializer_instance|
# whatever logic in here
end
end |
The problem that we started off with was how to avoid 'repetitive includes' in the controllers. Ex. if you have a 'Product' serializer with a has_one :price and has_one :image, you might |always| want to include those two associations since the product wont be complete without them. By default only the associations on the top-most object are serialized (to avoid cyclic dependencies) so if you are trying to include a Product through another serializer ex. "render @line_item, include: [:product]" then you would still want the product's price and image to be serialized but that wont be the case (since its nested), so you have to rewrite the render call as "render @line_item, include: ['product.price', 'product.image']" which causes unnecessary repetition wherever you want to serialize @line_item. You can bypass this issue by declaring the associations as attributes (which are always serialized even if nested) but thats a hack that we are trying to avoid. A simple solution would be to have an 'always_include' field on the associations. This field determines if the association should be included when the object in question is nested. The solution bf4 presented with the include/exclude is solving a different problem; where you only want to include/serialize specific fields on the target object instead of serializing the whole thing. Its a great feature but its not the same as 'always_include'. If you were to add both features to AMS then an association could look like this: "has_one :price, include: [:cost, :currency], always_include: true" i.e. both features can be used separately or in tandem. |
always_include: associations that should always be serialized even if the object is deeply nested. |
since acceptable values for |
I agree with both of you and I also think that we're getting some confusion here in order to allow too many different possibilities. @tommiller1 actually got straight to the point, the issue we want to solve is that sometimes an object really makes sense only when serialised with some associations. Or simply we need those associations to always be included when that object is serialised. To get this done, the On the other side, @bf4 have a good point on limiting the included attributes. Because maybe we do want to always include an association, but we don't need all its attributes. In this case, you can get the behaviour @tommiller1 wants with Another thing @bf4 doesn't probably like is the cascade-inclusion, which I think in this case would be preferable. On this matter, I would ask @NullVoxPopuli what he means exactly by "traversing the tree of default includes":
|
an example: class PostSerializer < AMS
default_include 'author,comments.author'
has_many :comments
belongs_to :author
end
class CommentSerializer < AMS
default_include 'replies'
belongs_to :post
belongs_to :author
has_many :replies
end I'll use include notation to keep things short, render json: post implies: render json: post, include: 'comments' since we only specified a default, this would mean your result would simply be but if we change the render json: post, include: 'comments' would be but then if we use include_always, how do we say we don't want it? using the except option for fields? render json: post, except: 'comments' yielding: does that help? |
Yes thanks! That's a lot clearer now :) I think that giving something powerful like I also like much more the So, trying to make everyone happy and foreseeing user cases, what do you think about: class PostSerializer < AMS
default_include '...'
always_include '...'
has_many :comments, only/include: [...]
belongs_to :author, except/exclude: [...]
end default_include: associations that you want to include by default (if you use json/attributes adapter, this defaults to all first-level associations). This value will be merged/overriden by the controller's render include. Both class PostSerializer < AM::S
default_include do |object, serializer_instance|
# whatever logic in here, must return a value to be parsed as JSONAPI::IncludeDirective
end
end |
Looks good to me, PR plx. |
Would like to agree with @bf4 and @NullVoxPopuli as well before coming back to #1845 and adding the association options. |
It's okay for solutions to exist in userland :). B mobile phone
|
@bf4 your thoughts on the above?
Does the difference lie on the position in the includes-tree of the serialiser? |
@NullVoxPopuli @bf4 sorry for chasing you, would really like to come back working on this asap 😄 |
I think my preference would be have it both ways. |
I'd like to come back too B mobile phone
|
It's fine for me, we can probably split it into 2 separate PR. |
@iMacTia I need a few things clarified here to understand the needs in AMS
I'm trying to understand to what extent the problem is that AMS is hard to customize vs. AMS isn't doing the right thing |
There's really no issue with AMS's customisation on any error with its implementation. |
@iMacTia I was writing an awesome response when github magically cleared it |
@bf4 I totally understand that, it's frustrating when it happens. |
@iMacTia yeah.. well GitHub is good at preserving comments in progress, but I had something that must have been in the flash cache that killed it... I'll try to come back to this at lunch today |
hi guys, any update on this? |
subscribed |
Update is that unfortunately |
IMHO supporting something like |
I believe there's an adapter unification rfc that hasn't yet been implemented
You can still do accepts_nested w jsonapi. Just deserialize first
… |
The Situation
I encourage to have a read to #1333 and #1845.
Let's assume we have the current serializers:
The issue
The only way to specify nested associations inclusion, at the moment, is through the controller's render
include
option, as shown in the current examples:The issue is that in this case (I admit is probably a stupid example, but stay with me), when rendering a post, we always want to render also its category name, its author attributes (except for the bio) and its author address.
(@bf4, I would like to specify the fields for author's address as well, but I'm not sure about how to do it in the controller's include.)
The proposed solution
The same result could be achieved without filling controller's with common serialisation logics, moving them into serialisers. For example, the above issue could have a more elegant solution like:
To be decided
We'll probably need some team discussion together with @bf4 and @NullVoxPopuli
Open questions:
include
be taken into consideration? Should we use only the ones in the class we're using to serialise? Does the above example make sense or should the Author's and Post'sinclude
s be ignored when serialising the Blog because they are on a deeper level?The text was updated successfully, but these errors were encountered: