Pergunta

Estou tentando construir uma representação JSON de alguns modelos Rails usando Active Model Serializer, onde alguns modelos incorporam outros.Por exemplo, tenho Evento e Participantes, Evento has_and_belongs_to_many Participantes.

class EventSerializer < ActiveModel::Serializer
  attributes :name

  has_many :attendees, serializer: AttendeeSerializer
end

class AttendeeSerializer < ActiveModel::Serializer
  attributes :name
end

Isso resultaria em JSON como { name: 'Event One', attendees: [{ name: 'Alice' }, { name: 'Bob' }] }.

Agora, gostaria de acrescentar o que os participantes disseram sobre o evento.Digamos que o comentário pertence_ao evento, pertence_ao participante.Eu gostaria de incluir esses comentários na saída serializada do evento, para que se tornasse { name: 'Event One', attendees: [{ name: 'Alice', comments: [{ text: 'Event One was great!'}] }, { name: 'Bob', comments: [] }] }.

eu poderia ter

class AttendeeSerializer < ActiveModel::Serializer
  attributes :name

  has_many :comments
end

mas isso selecionaria todos os comentários deste participante para todos os eventos - não o que eu quero.Eu gostaria de escrever isso, mas como encontro o evento específico para o qual estou fazendo a serialização?Posso de alguma forma acessar o objeto 'pai' ou talvez passar opções para um serializador 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

Isso é algo que pode ser feito ou devo apenas construir o JSON de outra maneira para este caso de uso específico?

Foi útil?

Solução

Eu faria as coisas manualmente para obter controle:

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top