active_model_serializers icon indicating copy to clipboard operation
active_model_serializers copied to clipboard

Specifying attributes of associated resources to be rendered excludes parent fields

Open acardnell-intruder opened this issue 2 years ago • 1 comments
trafficstars

Expected behavior vs actual behavior

I have a scenario similar to that outlined in the documentation. I want to restrict the fields serialized on my associations via the controller whilst retaining the fields specified in the serializer for the parent.

Example:

render json: @posts, include: 'comments', fields: [ comments: ['content', 'created_at'] ]

In this example it will correctly serialize only the content and created_at fields for the comments, but it will no longer return any fields for the posts.

I narrowed this down to the fields_to_fieldset method on the ActiveModelSerializers::Adapter::Attributes. The method will always add an empty array for the parent model because of line 32, and the empty array is by default interpreted to return no fields:

relationship_fields.merge!(serializer.json_key.to_sym => resource_fields)

I appreciate the documentation I linked only mentions this syntax works for json_api, so perhaps this behaviour is intended, but I would appreciate being able to override it because currently the only workaround I have found is to specify all the attributes in the serializer again in the fields.

Environment

ActiveModelSerializers Version (commit ref if not on tag):

I tested this with version 10.0.0 and 10.0.13 - both had the same issue.

Integrated application and version (e.g., Rails, Grape, etc):

Rails: 7.0.4 Ruby: 3.0.5

acardnell-intruder avatar Dec 13 '22 21:12 acardnell-intruder

For anyone looking for a workaround that doesn't involve manually listing all the attributes from the serializer in the fields, the following should work:

attributes = PostSerializer._attributes
render json: @posts, include: 'comments', fields: [ *attributes, comments: ['content', 'created_at'] ]

In addition, for nested relation of relations, the following will also work:

attributes = PostSerializer._attributes
render json: @posts, include: [:comments, 'comments.tags'], fields: [ *attributes, comments: ['content', 'created_at'], tags: ['name'] ]

acardnell-intruder avatar Dec 15 '22 18:12 acardnell-intruder