Ограничение каскада ассоциаций в Active Model Serializer

У меня возникла проблема с ограничением уровня ассоциаций, сериализованных в активном ресурсе модели.

Например:

В игре много команд, в которых много игроков.

class GameSerializer < ActiveModel::Serializer
  attributes :id
  has_many :teams
end

class TeamSerializer < ActiveModel::Serializer
  attributes :id
  has_many :players
end

class PlayerSerializer < ActiveModel::Serializer
  attributes :id, :name
end

Когда я получаю JSON для команды, он включает всех игроков в подмассиве по желанию.

Когда я получаю JSON для игры, он включает в себя все команды в подмассиве, отлично, но также и всех игроков для каждой команды. Это ожидаемое поведение, но можно ли ограничить уровень ассоциаций? Возвращать ли Game только сериализованные команды без игроков?


person Greg Olsen    schedule 01.05.2013    source источник


Ответы (2)


Другой вариант — злоупотреблять нетерпеливой загрузкой Rails, чтобы определить, какие ассоциации отображать:

В вашем контроллере рельсов:

def show
  @post = Post.includes(:comments).find(params[:id])
  render json: @post
end

затем в земле AMS:

class PostSerializer < ActiveModel::Serializer
  attributes :id, :title
  has_many :comments, embed: :id, serializer: CommentSerializer, include: true

  def include_comments?
    # would include because the association is hydrated
    object.association(:comments).loaded?
  end
end

Вероятно, не самое чистое решение, но оно прекрасно работает для меня!

person Kieran Huggins    schedule 23.09.2013
comment
object.association(:comments).loaded? Это именно то, что я искал, спасибо! Я думаю, что этот метод чище, чем принятый ответ. Из документации active_model_serializer рекомендуется включать ассоциации, используя либо соединение, либо включение в контроллер, чтобы избежать запросов n+1. Где я был в тупике, так это в сериализаторе, как определить, загружена ли ассоциация или опустить ее. Из документов: старайтесь избегать запросов n+1, обеспечивая оптимальную загрузку данных, например. если вы используете ActiveRecord, вы можете использовать запросы, включающие или присоединяющиеся по мере необходимости. - person Mark; 28.10.2013
comment
Где я должен вызывать include_comments? метод? - person Kaspar; 08.12.2014

Вы можете создать еще один Serializer:

class ShortTeamSerializer < ActiveModel::Serializer
  attributes :id
end

Затем:

class GameSerializer < ActiveModel::Serializer
  attributes :id
  has_many :teams, serializer: ShortTeamSerializer
end

Или вы можете определить include_teams? в GameSerializer:

class GameSerializer < ActiveModel::Serializer
  attributes :id
  has_many :teams

  def include_teams?
    @options[:include_teams]
  end
end
person Pablo B.    schedule 11.08.2013
comment
Спасибо, Пабло, вот что я в итоге сделал... Я попытался сделать это немного рельсовым, моделируя множественное число :index и :show, но используя TeamsSerializer и TeamSerializer. Особые случаи получают другой сериализатор. - person Greg Olsen; 14.08.2013
comment
Откуда взялись @options? - person Samnang; 22.01.2014