web-dev-qa-db-ja.com

Railsアクティブモデルシリアライザ-has_manyと親レコードへのアクセス

アクティブモデルシリアライザを使用して、いくつかのRailsモデルのJSON表現を構築しようとしています。たとえば、一部のモデルは他のモデルを埋め込みます。たとえば、イベントと出席者、イベントhas_and_belongs_to_many出席者があります。

class EventSerializer < ActiveModel::Serializer
  attributes :name

  has_many :attendees, serializer: AttendeeSerializer
end

class AttendeeSerializer < ActiveModel::Serializer
  attributes :name
end

これにより、JSONは{ name: 'Event One', attendees: [{ name: 'Alice' }, { name: 'Bob' }] }のようになります。

さて、参加者がイベントについて言ったことを追加したいと思います。たとえば、Comment belongs_toイベント、belongs_toの参加者です。上記のコメントをイベントのシリアル化された出力に含めたいので、それは{ name: 'Event One', attendees: [{ name: 'Alice', comments: [{ text: 'Event One was great!'}] }, { name: 'Bob', comments: [] }] }になります。

ができた

class AttendeeSerializer < ActiveModel::Serializer
  attributes :name

  has_many :comments
end

しかし、それでは、この出席者がすべてのイベントに対してすべてのコメントを選択することになります-私が望むものではありません。これを書きたいのですが、シリアル化している特定のイベントをどのように見つけますか?どういうわけか「親」オブジェクトにアクセスできますか、またはオプションを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

これは実行できるものですか、それともこの特定のユースケースでは別の方法でJSONを作成するだけですか?

18
Toms Mikoss

手動で制御を取得します。

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
46
apneadiving