web-dev-qa-db-fra.com

Attributs conditionnels dans les sérialiseurs de modèles actifs

Comment rendre un attribut uniquement si une condition est vraie?

Par exemple, je souhaite rendre l'attribut de jeton de l'utilisateur lors de la création d'une action.

41
Dan

Vous pouvez également le faire de cette façon:

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

  def condition?
    #condition code goes here
  end
end

Par exemple:

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

EDIT (suggéré par Joe Essey ):

Cette méthode ne fonctionne pas avec la dernière version (0.10)

Avec la version 0.8 c'est encore plus simple. Vous n'êtes pas obligé d'utiliser le if: :condition?. Au lieu de cela, vous pouvez utiliser la convention suivante pour obtenir le même résultat.

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

  def include_conditional_attr?
    #condition code goes here
  end
end

L'exemple ci-dessus ressemblerait à ceci.

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

Voir documentation 0.8 pour plus de détails.

63
Abdelhakim AKODADI

vous pouvez remplacer la méthode attributes, voici un exemple simple:

class Foo < ActiveModel::Serializer

  attributes :id

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

end
44
apneadiving

Vous pouvez commencer par définir une condition sur la méthode d'initialisation des sérialiseurs. Cette condition peut être passée de n'importe où ailleurs dans votre code, incluse dans le hachage d'options que "initialize" accepte comme deuxième argument:

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

Dans ce cas, attr1 sera toujours transmis, tandis que les attributs conditionnels seront masqués si la condition est vraie.

Vous obtiendriez le résultat de cette sérialisation personnalisée partout ailleurs dans votre code comme suit:

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

J'espère que c'était utile!

3
froskos

Serializer options ont été fusionnés dans ActiveModel Serializers et sont maintenant disponibles (depuis 0.10).

2
Dan

Remplacer est une bonne idée, mais si vous utilisez le super les attributs seront calculés avant de supprimer ce que vous voulez. Si cela ne fait aucune différence pour vous, d'accord, mais quand c'est le cas, vous pouvez l'utiliser:

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