Rails Active Model Serializer – has_many und Zugriff auf den übergeordneten Datensatz
-
20-12-2019 - |
Frage
Ich versuche, mithilfe des Active Model Serializer eine JSON-Darstellung einiger Rails-Modelle zu erstellen, wobei einige Modelle andere einbetten.Zum Beispiel habe ich Event und Teilnehmer, 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
Dies würde zu einem JSON-ähnlichen Ergebnis führen { name: 'Event One', attendees: [{ name: 'Alice' }, { name: 'Bob' }] }
.
Nun möchte ich hinzufügen, was die Teilnehmer über die Veranstaltung gesagt haben.Nehmen wir an, Kommentar gehört_zum Ereignis, gehört_zum Teilnehmer.Ich würde diese Kommentare gerne in die serialisierte Ausgabe von event aufnehmen, damit es so wird { name: 'Event One', attendees: [{ name: 'Alice', comments: [{ text: 'Event One was great!'}] }, { name: 'Bob', comments: [] }] }
.
ich könnte haben
class AttendeeSerializer < ActiveModel::Serializer
attributes :name
has_many :comments
end
aber das würde alle Kommentare dieses Teilnehmers für alle Veranstaltungen auswählen – nicht das, was ich möchte.Ich würde das gerne schreiben, aber wie finde ich das bestimmte Ereignis, für das ich die Serialisierung durchführe?Kann ich irgendwie auf das „übergeordnete“ Objekt zugreifen oder Optionen an einen has_many-Serializer übergeben?
class AttendeeSerializer < ActiveModel::Serializer
attributes :name
has_many :comments
def comments
object.comments.where(event_id: the_event_in_this_context.id)
end
end
Ist das möglich, oder sollte ich JSON für diesen speziellen Anwendungsfall einfach auf andere Weise erstellen?
Lösung
Ich würde die Dinge manuell erledigen, um die Kontrolle zu erlangen:
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