Active Model Serializers中的条件属性

时间:2015-04-17 17:28:56

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

如果某些条件为真,我该如何渲染属性?

例如,我想在create action上呈现User的令牌属性。

6 个答案:

答案 0 :(得分:51)

你也可以这样做:

class EntitySerializer < ActiveModel::Serializer
  attributes :id, :created_at, :updated_at
  attribute :conditional_attr, if: :condition?

  def condition?
    #condition code goes here
  end
end

例如:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :username, :name, :email, :created_at, :updated_at
  attribute :auth_token, if: :auth_token?

  def created_at
    object.created_at.to_i
  end

  def updated_at
    object.updated_at.to_i
  end

  def auth_token?
    true if object.auth_token
  end
end

编辑(由Joe Essey建议):

此方法不适用于最新版本(0.10

版本0.8更简单。您不必使用if: :condition?。相反,您可以使用以下约定来实现相同的结果。

class EntitySerializer < ActiveModel::Serializer
  attributes :id, :created_at, :updated_at
  attribute :conditional_attr

  def include_conditional_attr?
    #condition code goes here
  end
end

上面的例子看起来像这样。

class UserSerializer < ActiveModel::Serializer
  attributes :id, :username, :name, :email, :created_at, :updated_at
  attribute :auth_token

  def created_at
    object.created_at.to_i
  end

  def updated_at
    object.updated_at.to_i
  end

  def include_auth_token?
    true if object.auth_token
  end
end

有关详细信息,请参阅0.8 documentation

答案 1 :(得分:41)

你可以覆盖attributes方法,这是一个简单的例子:

class Foo < ActiveModel::Serializer

  attributes :id

  def attributes(*args)
    hash = super
    hash[:last_name] = 'Bob' unless object.persisted?
    hash
  end

end

答案 2 :(得分:3)

您可以首先在序列化程序'initialize'方法上设置条件。这个条件可以从代码中的任何其他位置传递,包含在'initialize'接受的选项哈希中作为第二个参数:

class SomeCustomSerializer < ActiveModel::Serializer

  attributes :id, :attr1, :conditional_attr2, :conditional_attr2

  def initialize(object, options={})
    @condition = options[:condition].present? && options[:condition]
    super(object, options)
  end

  def attributes(*args)
    return super unless @condition  #get all the attributes
    attributes_to_remove = [:conditional_attr2, :conditional_attr2]
    filtered = super.except(*attributes_to_remove)
    filtered
  end
end

在这种情况下,将始终传递attr1,而如果条件为真,则隐藏条件属性。

您可以在代码中的任何其他地方获得此自定义序列化的结果,如下所示:

custom_serialized_object = SomeCustomSerializer.new(object_to_serialize, {:condition => true})

我希望这很有用!

答案 3 :(得分:2)

序列化程序options已合并到ActiveModel序列化程序中,现在可用(从0.10开始)。

答案 4 :(得分:1)

这里介绍了如何将参数直接传递给序列化程序实例,并根据序列化程序声明中的这些参数显示隐藏属性。

它也适用于父子序列化程序。

控制器或父序列化器:

ActiveModelSerializers::SerializableResource.new(object.locations, {
  each_serializer: PublicLocationSerializer,
  params: { 
    show_title: true
  },
})

带条件的序列化程序:

class PublicLocationSerializer < ActiveModel::Serializer
  attributes :id, :latitude, :longitude, :title

  def title
    object.title if @instance_options[:params][:show_title]
  end

end

答案 5 :(得分:0)

覆盖是一个好主意,但如果您使用super,则会在删除所需内容之前计算属性。如果它对你没有影响,那么,但是当它发生时,你可以使用它:

def attributes(options={})
  attributes =
    if options[:fields]
      self.class._attributes & options[:fields]
    else
      self.class._attributes.dup
    end

  attributes.delete_if {|attr| attr == :attribute_name } if condition

  attributes.each_with_object({}) do |name, hash|
    unless self.class._fragmented
      hash[name] = send(name)
    else
      hash[name] = self.class._fragmented.public_send(name)
    end
  end
end

ps:v0.10.0.rc3