-
Firstly, thanks for your work on this, it looks pretty great and very performant. I'm hoping you could expand on the composability section of the readme. Also wondering if you have any suggestions for creating seralizers which would change slightly for each view. For instance, if I have an Articles model, I would likely want to send all fields and all associations to the "show" view, but I might only need to send the Thank you |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hi Avram!
Typically the way I like to structure them, is to create one serializer per "use case". For example, you might have a lighter serializer for an Because serializers should not typically contain business logic, unless the difference is very simple, I'd typically avoid using inheritance and specify the full list of attributes that are needed upfront. The benefit of that, is that adding more attributes to one "endpoint" does not accidentally add that unnecessarily to other endpoints, which can be hard to notice (and could affect performance indirectly via additional queries). class SongIndexSerializer < BaseSerializer
attributes(
:id,
:title,
)
end
class SongDetailsSerializer < BaseSerializer
attributes(
:id,
:title,
)
has_one :composer, serializer: ComposerSerializer
has_many :video_clips, as: :videos, serializer: VideoSerializer
end Although at first this seems like "a lot of duplication", in most cases it doesn't have any downsides, and in the long term it simplifies maintenance and refactoring, and prevents accidental breakage. Having different classes makes usages easier to find, and the code is easier to reason about (what you see is what you get). However, just to illustrate what you can do in cases where the data should be "shared": class SongSerializer < BaseSerializer
attributes(
:id,
:title,
)
has_one :composer, serializer: ComposerSerializer
has_many :video_clips, as: :videos, serializer: VideoSerializer, if: ->{ options[:include_videos] }
end
SongSerializer.one(song, include_videos: true) You could use this same pattern with class SongSerializer < BaseSerializer
attributes(
:id,
:title,
)
class Detailed < BaseSerializer
has_one :composer, serializer: ComposerSerializer
has_many :video_clips, as: :videos, serializer: VideoSerializer
end
flat_one :song, serializer: Detailed, if: -> { options[:view] == :detailed }
end
SongSerializer.one(song, view: :detailed) In the future I might add this as a built-in |
Beta Was this translation helpful? Give feedback.
Hi Avram!
Typically the way I like to structure them, is to create one serializer per "use case".
For example, you might have a lighter serializer for an
index
page, and a serializer with more info for ashow
page.Because serializers should not typically contain business logic, unless the difference is very simple, I'd typically avoid using inheritance and specify the full list of attributes that are needed upfront.
The benefit of that, is that adding more attributes to one "endpoint" does not accidentally add that unnecessarily to other endpoints, which can be hard to notice (and could affect performance…