Description
tl;dr
We need better serializer lookup in order to handle namespaces, which brings the opportunity to handle nested serializers, and introduce a friendly syntax to declare them.
As you may have noticed, there is currently some work being done on nested serialization. Different needs have been identified:
- nesting some or all of the relationships (this is taken care of by Add support for wildcards in nested includes #1158 and Support nested associations for Json and Attributes adapters + Refactor Attributes adapter #1127) via the
include
adapter option (which allows to specify a potentially infinite (via wildcards) inclusion tree) - nesting some or all of the relationships, and contextually (depending on the serializer) choosing which attributes to serialize (which is taken care of by Add support for nested serializers. #1157, although not currently perfect: specifying a nested serializer forces you to redundantly specify the relationships in the
include
adapter option, unless you set it to**
, in which case only the nested serializers are used) - conditionally include/exclude attributes from a serializer (for instance depending on some authorization primitive), which is being discussed in Attribute filtering for 0.10.x #1141
I think the state of 1. is satisfying.
For 2., we could either extend the include
option to handle attributes as well, but this would lead to implicitly defining nested serializers, which is IMO more confusing than actually defining nested serializers (as in #1157). With #1157, nesting serializers works as follows:
PostSerializer < ActiveModel::Serializer
attributes :title, :body
belongs_to :author
AuthorSerializer < ActiveModel::Serializer
attributes :name
has_many :comments
CommentSerializer < ActiveModel::Serializer
attributes :body, :date
belongs_to :author # This would be serialized by PostSerializer::AuthorSerializer, unless we define a PostSerializer::CommentSerializer::AuthorSerializer
end
end
I would be in favor of introducing the following syntax:
PostSerializer < ActiveModel::Serializer
attributes :title, :body
belongs_to :author do
attributes :name
end
has_many :comments do
attributes :body, :date
belongs_to :author # This would be serialized by PostSerializer::AuthorSerializer, unless we define a PostSerializer::CommentSerializer::AuthorSerializer
end
end
in conjunction with a default behavior of either including all nested relationships, or at least all nested relationships for which a nested serializer has been provided.
For 3., I think we should either have something like
attribute :secret_stuff, include_if: { object == current_user || current_user.admin? }
or something more like 0.8.x
def include_attributes(included) # I purposely did not use "filter" because it has a specific sense in the scope of JSON API
if current_user.admin?
included
else
included.except([:secret_stuff1, :secret_stuff2])
end
end
or maybe both.
Questions? Suggestions? PRs?
UPDATE:
#1225 brings support for nested serializers (and automatically uses serializers in the same namespace as the resource)
#1226 brings support for the block syntax