active_model_serializers
active_model_serializers copied to clipboard
Rails 5, ActiveRecord has_many for nested Serializers not used?
Probably doing something wrong, but ...
Expected behavior vs actual behavior
Given the following models & serialisers:
class Shipment < ApplicationRecord
has_many :shipment_service_types
end
class ShipmentServiceType < ApplicationRecord
belongs_to :shipment
has_many :time_windows
end
class TimeWindow < ApplicationRecord
belongs_to :shipment_service_type
end
# serializers
class ShipmentSerializer < ActiveModel::Serializer
attributes :id, :name
has_many :shipment_service_types, serializer: ShipmentServiceTypeSerializer
end
class ShipmentServiceTypeSerializer < ActiveModel::Serializer
attributes :name
has_many :time_windows, serializer: TimeWindowSerializer
end
class TimeWindowSerializer < ActiveModel::Serializer
attributes :id, :start, :end
end
The output I expect to see is:
{
"shipment": {
"id": 1,
"name": "Test",
"shipment_service_types": [
{
"id": 1,
"name": "test",
"time_windows": [
{
"id": 1,
"start": "2000-01-01 09:05:41 UTC",
"end": "2000-01-01 10:05:41 UTC"
}
]
}
]
}
}
What I'm getting is:
{
"shipment": {
"id": 1,
"name": "Test",
"shipment_service_types": [
{
"id": 1,
"name": "test"
}
]
}
}
Steps to reproduce
(e.g., detailed walkthrough, runnable script, example application)
I've made an example app: https://github.com/tdegrunt/ams_test
Environment
ActiveModelSerializers Version (commit ref if not on tag):
Output of ruby -e "puts RUBY_DESCRIPTION"
:
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-darwin15]
OS Type & Version: macOS 10.12.2
Integrated application and version (e.g., Rails, Grape, etc): Rails 5.0.1
Backtrace
(e.g., provide any applicable backtraces from your application)
Additonal helpful information
(e.g., Gemfile.lock, configurations, PR containing a failing test, git bisect results)
@rails-api/ams @rails-api/commit we really need to improve the docs on nesting more than 2 levels deep. This comes up not infrequently.
@bf4 totally agree on this. And I would actually say, the whole docs need to be improved.
@tdegrunt I guess what you are missing is the include
option as per https://github.com/rails-api/active_model_serializers/blob/a032201a91cbca407211bca0392ba881eef1f7ba/docs/general/adapters.md#included (this is for the JSONAPI adapter but it works the same for the JSON adapter). Try adding the option include: "shipment_service_types,shipment_service_types.time_windows"
. So:
render json: resource, include: "shipment_service_types,shipment_service_types.time_windows"
👍 would be an epic pr
Ah thanks, totally missed that. Is this done because of performance benefits? It's kind of contrary to the "just works" principle. From that perspective "exclude" would almost make more sense? Anyways, I can continue upgrading to v0.10/master. Am a happy camper regardless! :)
AFAIK it's more about avoiding serializing recursive relationships and finer control over what is included in the response. Maybe that goes against our dev instincts. It is still possible to use ActiveModelSerializers.config.default_includes = "**"
to include every relationship by default if you know what you're doing though.
The include ** is an idiosyncrasy of ams... I'd rather make it annoying to write deeply nested structures as a way of dissuading their usage. Sometimes it's good to make something hard. :)
Best practice is to flatten resources like json api does. Easier to manage, less redundant
B mobile phone
On Dec 27, 2016, at 8:54 AM, Yohan Robert [email protected] wrote:
AFAIK it's more about avoiding serializing recursive relationships and finer control over what is included in the response. Maybe that goes against our dev instincts. It is still possible to use ActiveModelSerializers.config.default_includes = "**" to include every relationship by default if you know what you're doing though.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
- https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/adapters.md#included
- https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/configuration_options.md#default_includes
+1
This is a pretty severe performance bottleneck for me since the API I manage has a lot of nested relations, sometimes going 3-4 layers deep. An ideal solution IMO would be (if possible) to just include
whatever was in the includes
statement of the query if one was present.
@groyoh Thanks for the solution you posted above:
render json: resource, include: "shipment_service_types,shipment_service_types.time_windows"
If you wanted to limit that query to the last 10 shipment_service_types.time_windows
and sort them in descending order, is that possible?
The include
directive also supports hash
:
render json: @accommodation, include: [
:category,
:owner,
:average,
:images,
:commodities,
:facilitations,
rooms: [
:commodities,
:facilitations,
beds: [
:category
]
]
]