active_model_serializers
active_model_serializers copied to clipboard
0.10.x: associations are not included when nested
Expected behavior vs actual behavior
If I have an object: cat = Cat.find_by_name('fluffy')
and assume that I can do: cat.paws.last.claws.count => 5 cat.paws.first.claws.count => 4
...
If my controller renders out the cat with a nested serializer structure such as: respond_with cat, :serializer => CatSerializer
...
class ClawSerializer < ActiveModel::Serializer
attribute :sharpness
end
class PawSerializer < ActiveModel::Serializer
attribute :position
has_many :claws, :serializer => ClawSerializer
end
class CatSerializer < ActiveModel::Serializer
attribute :name
has_many :paws, :serializer => PawSerializer
end
...
I get the json structure:
{
name: 'fluffy',
paws: [
{ position: 0 },
{ position: 1 },
{ position: 2 },
{ position: 3 },
]
}
With no claws...
Yet again, if I explicitly do:
class PawSerializer < ActiveModel::Serializer
attribute :claws
attribute :position
def claws
object.claws.map do |claw|
ClawSerializer.new(claw)
end
end
end
Then I get the structure I expect:
{
name: 'fluffy',
paws: [
{ position: 0, claws: [ { sharp: true }, { sharp: true }, { sharp: true }, { sharp: true }, { sharp: true } ] },
{ position: 1, claws: [ { sharp: true }, { sharp: true }, { sharp: true }, { sharp: true }, { sharp: true } ] },
{ position: 2, claws: [ { sharp: false }, { sharp: false }, { sharp: false }, { sharp: false }, { sharp: false } ] },
{ position: 3, claws: [ { sharp: false }, { sharp: false }, { sharp: false }, { sharp: false }, { sharp: false } ] },]
]
}
Have you tried using the include
option in your controller? I believe you have to explicitly state the associations you wish to include: https://github.com/rails-api/active_model_serializers/blob/master/docs/general/adapters.md#include-option
You can also see an example of this in the tests: https://github.com/rails-api/active_model_serializers/blob/master/test/action_controller/json/include_test.rb#L43
I thought that was only if you are using the json api adapter? Because I am not using that adapter...
@patrick99e99 I believe it's for the JSON and JSON API adapter, the docs are a little unclear there. I haven't tested it with the attributes adapter myself.
Just spent some time trying to get my head around this too, as I have a really similar problem to @patrick99e99 but using a has_one
instead of has_many
and ended up with a similar solution too... as in calling another serializer from a serializer to get the output I wanted as the nested association didn't work as I thought it would (or should).
So is it the case that nested associations should work and don't or has it never been the case and people should alway put include
in their controllers?
Also, and this might be me being dumb, but shouldn't creating serializers mean we shouldn't have to continue to use include
in our controllers? I guess what I mean is shouldn't there be a way to specify the includes in the serializers?
BTW it did work as expected if I put the include
in the controller.
@patrick99e99 From https://github.com/rails-api/active_model_serializers/blob/v0.10.6/docs/general/configuration_options.md
default_includes What relationships to serialize by default. Default: '*', which includes one level of related objects. >See includes for more info.
To serialize all associations by default set ActiveModelSerializers.config.default_includes = '**'
how about this? I use it to fix has_one problem about not included in nested case.
attirbute :foo do
FooSerializer.new object.foo
end
@cactis the standard way AMS suggests is to define the has_one association using the same keyword in the serializer:
# some_serializer.rb
has_one :foo
and in the controller, render it along with the include
option putting a value of **
in it if the parent of this association (the object of the above serializer) is at least 1-level deep from the controller resource.