如何在Active Model Serializers上动态添加属性

时间:2014-11-15 00:59:33

标签: ruby-on-rails-4 active-model-serializers

我想决定在我的控制器中输出的属性数量。

但我不知道该怎么做?

controller.rb

  respond_to do |format|
    if fields
      # less attributes : only a,c
    elsif xxx
      # default attributes
    else
      # all attributes : a,c,b,d,...
    end
  end

serializer.rb

class WeatherLogSerializer < ActiveModel::Serializer
  attributes :id, :temperature
  def temperature
    "Celsius: #{object.air_temperature.to_f}"
  end
end

2 个答案:

答案 0 :(得分:13)

我可能会为所有人使用不同的端点,但您也可以传入不同的url参数或类似的东西。通常情况下,我认为您希望默认值更加有限。

以下是我建议的方式:

控制器

所有人的不同终点

render json: objects, each_serializer: WeatherLogAllSerializer

允许自定义字段

fields = params[:fields] # Csv string of specified fields.

# pass the fields into the scope
if fields.present?
  render json: objects, each_serializer: WeatherLogCustomSerializer, scope: fields
else
  render json: objects, each_serializer: WeatherLogSerializer
end

三种不同的序列化程序:all,default,custom

所有

class WeatherLogAllSerializer < ActiveModel::Serializer
  attributes :id, :temperature, :precipitation, :precipitation
  has_many :measurements

  def temperature
    "Celsius: #{object.air_temperature.to_f}"
  end
end

默认

class WeatherLogSerializer < ActiveModel::Serializer
  attributes :id, :temperature
  def temperature
    "Celsius: #{object.air_temperature.to_f}"
  end
end

自定义

class WeatherLogCustomSerializer < WeatherLogSerializer

  def attributes
    data = super
    if scope
      scope.split(",").each do |field|
        if field == 'precipitation'
          data[:precipitation] = object.precipitation
        elsif field == 'humidity'
          data[:humidity] = object.humidity
        elsif field == 'measurements'
          data[:measurements] = ActiveModel::ArraySerializer.new(object.measurements)
        end
      end
    end
    data
  end
end

答案 1 :(得分:2)

您可以使用自定义序列化程序创建不同的序列化程序和respond_withrender,如下所示:

# serialize an array of WeatherLog(s)
render json: objects, each_serializer: WeatherLogSerializer
# serialize a WeatherLog
render json: object, serializer: WeatherLogSimpleSerializer 

# just gimme id and temp
class WeatherLogSimpleSerializer < ActiveModel::Serializer
  attributes :id, :temperature
  def temperature
    "Celsius: #{object.air_temperature.to_f}"
  end
end

# gimme everything
class WeatherLogSerializer < ActiveModel::Serializer
  attributes(*WeatherLog.attribute_names.map(&:to_sym))
end