как условно включить ассоциации в Rails Active Model Serializer v0.8

Я использовал AMS (0.8) с Rails 3.2.19, но одно место, где я действительно борюсь с ними, - это то, как контролировать, включают ли сериализаторы свои ассоциации или нет. Очевидно, я использую AMS для создания JSON API. Иногда сериализатор является конечным или самым дальним элементом, а иногда — верхним уровнем и должен включать ассоциации. Мой вопрос в том, как лучше всего это сделать, или это решение, которое я делаю ниже работы (или это лучшее решение).

Я видел некоторые обсуждения, но я нахожу их очень запутанными (и основанными на версиях). Ясно, что для атрибутов или ассоциаций Serializer есть include_XXX? метод для каждого, и здесь вы можете вернуть либо истинное, либо ложное утверждение.

Вот мой предложенный код - это винодел, у которого много wine_items. Вот как бы вы это сделали?

Классы моделей:

class WineItem < ActiveRecord::Base
  attr_accessible :name, :winemaker_id
  belongs_to :winemaker

end

class Winemaker < ActiveRecord::Base
  attr_accessible :name
  has_many :wine_items
  attr_accessor :show_items
end

Сериализаторы:

class WinemakerSerializer < ActiveModel::Serializer
  attributes :id, :name
  has_many :wine_items 

  def include_wine_items?
    object.show_items
  end
end

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

и в моем контроллере:

class ApiWinemakersController < ApplicationController
  def index
    @winemakers=Winemaker.all
    @winemakers.each { |wm| wm.show_items=true }
    render json: @winemakers, each_serializer: WinemakerSerializer, root: "data"
  end
end

person timpone    schedule 02.12.2014    source источник
comment
AMS 0.10.2: не работает. def include_wine_items? не имеет никакого эффекта - независимо от того, возвращает ли он значение true или false, ассоциация включена.   -  person prograils    schedule 15.02.2017


Ответы (1)


Я сам столкнулся с этой проблемой, и пока это самое чистое решение (но я не фанат этого).

Этот метод позволяет вам делать такие вещи, как:

/parents/1?include_children=true

или используя более чистый синтаксис, например:

/parents/1?include=[children] и т.д...

# app/controllers/application_controller.rb
class ApplicationController
  # Override scope for ActiveModel-Serializer (method defined below)
  # See: https://github.com/rails-api/active_model_serializers/tree/0-8-stable#customizing-scope
  serialization_scope(:serializer_scope)

  private

  # Whatever is in this method is accessible in the serializer classes.
  # Pass in params for conditional includes.
  def serializer_scope
    OpenStruct.new(params: params, current_user: current_user)
  end
end

# app/serializers/parent_serializer.rb
class ParentSerializer < ActiveModel::Serializer
  has_many :children

  def include_children?
    params[:include_children] == true
    # or if using other syntax:
    # params[:includes].include?("children")
  end
end

Немного хакерски для меня, но это работает. Надеюсь, что вы найдете ее полезной!

person Dan L    schedule 29.01.2015
comment
AMS 0.10.2: не работает. определение include_children? не имеет никакого эффекта - независимо от того, возвращает ли он true или false, ассоциация включена. - person prograils; 15.02.2017