J'essaie de créer une représentation JSON de certains modèles Rails utilisant Active Model Serializer, où certains modèles en incorporent d'autres. Par exemple, j'ai Event et Participants, Event has_and_belongs_to_many Attendees.
class EventSerializer < ActiveModel::Serializer
attributes :name
has_many :attendees, serializer: AttendeeSerializer
end
class AttendeeSerializer < ActiveModel::Serializer
attributes :name
end
Cela entraînerait JSON comme { name: 'Event One', attendees: [{ name: 'Alice' }, { name: 'Bob' }] }
.
J'aimerais maintenant ajouter ce que les participants ont dit à propos de l'événement. Disons que le commentaire appartient à l'événement, appartient au participant. Je voudrais inclure ces commentaires dans la sortie sérialisée de l'événement, afin qu'il devienne { name: 'Event One', attendees: [{ name: 'Alice', comments: [{ text: 'Event One was great!'}] }, { name: 'Bob', comments: [] }] }
.
J'aurais pu
class AttendeeSerializer < ActiveModel::Serializer
attributes :name
has_many :comments
end
mais cela sélectionnerait tous les commentaires de ce participant pour tous les événements - pas ce que je veux. J'aimerais écrire ceci, mais comment trouver l'événement particulier pour lequel je fais la sérialisation? Puis-je en quelque sorte accéder à l'objet "parent", ou peut-être passer des options à un sérialiseur has_many?
class AttendeeSerializer < ActiveModel::Serializer
attributes :name
has_many :comments
def comments
object.comments.where(event_id: the_event_in_this_context.id)
end
end
Est-ce quelque chose qui peut être fait, ou dois-je simplement construire le JSON d'une autre manière pour ce cas d'utilisation particulier?
Je ferais les choses manuellement pour prendre le contrôle:
class EventSerializer < ActiveModel::Serializer
attributes :name, :attendees
def attendees
object.attendees.map do |attendee|
AttendeeSerializer.new(attendee, scope: scope, root: false, event: object)
end
end
end
class AttendeeSerializer < ActiveModel::Serializer
attributes :name, :comments
def comments
object.comments.where(event_id: @options[:event].id).map do |comment|
CommentSerializer.new(comment, scope: scope, root: false)
end
end
end