web-dev-qa-db-ja.com

アクティブモデルシリアライザーの条件付き属性

一部の条件が真の場合にのみ属性をレンダリングするにはどうすればよいですか?

たとえば、作成アクションでユーザーのトークン属性をレンダリングしたいとします。

41
Dan

次のようにすることもできます:

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

詳細は .8ドキュメント を参照してください。

63

attributesメソッドをオーバーライドできます。簡単な例を次に示します。

class Foo < ActiveModel::Serializer

  attributes :id

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

end
44
apneadiving

まず、シリアライザの 'initialize'メソッドに条件を設定します。この条件は、コードのどこからでも渡すことができ、「初期化」が2番目の引数として受け入れるオプションハッシュに含まれます。

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は常に渡されますが、条件がtrueの場合、条件付き属性は非表示になります。

次のように、コード内の他の場所でこのカスタムシリアル化の結果を取得します。

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

これがお役に立てば幸いです。

3
froskos

シリアライザ オプション はActiveModelシリアライザに統合され、現在利用可能です(0.10以降)。

2
Dan

オーバーライドは良い考えですが、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

0
Passalini