Voorwaardelijke kenmerken in Active Model Serializers

Hoe geef ik een attribuut alleen weer als een voorwaarde waar is?

Ik wil bijvoorbeeld het tokenkenmerk van de gebruiker weergeven bij het maken van een actie.


Antwoord 1, autoriteit 100%

In de nieuwste versie (0.10.x) kun je het ook op deze manier doen:

class EntitySerializer < ActiveModel::Serializer
  attributes :id, :created_at, :updated_at
  attribute :conditional_attr, if: :condition?
  def condition?
    #condition code goes here
  end
end

Bijvoorbeeld:

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 (Voorgesteld door Joe Essey) :

Deze methode werkt niet met de nieuwste versie (0.10)

Met de versie 0.8is het nog eenvoudiger. U hoeft de if: :condition?niet te gebruiken. In plaats daarvan kunt u de volgende conventie gebruiken om hetzelfde resultaat te bereiken.

class EntitySerializer < ActiveModel::Serializer
  attributes :id, :created_at, :updated_at
  attribute :conditional_attr
  def include_conditional_attr?
    #condition code goes here
  end
end

Het bovenstaande voorbeeld ziet er als volgt uit.

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

Zie 0.8 documentatievoor meer details.


Antwoord 2, autoriteit 62%

u kunt de methode attributesoverschrijven, hier is een eenvoudig voorbeeld:

class Foo < ActiveModel::Serializer
  attributes :id
  def attributes(*args)
    hash = super
    hash[:last_name] = 'Bob' unless object.persisted?
    hash
  end
end

Antwoord 3, autoriteit 5%

Je zou kunnen beginnen met het instellen van een voorwaarde voor de serializers ‘initialize’-methode. Deze voorwaarde kan worden doorgegeven van waar dan ook in uw code, opgenomen in de hash-opties die ‘initialiseren’ als tweede argument accepteert:

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

In dit geval zou attr1 altijd worden doorgegeven, terwijl de voorwaardelijke kenmerken verborgen zouden zijn als de voorwaarde waar is.

Je krijgt het resultaat van deze aangepaste serialisatie waar dan ook in je code als volgt:

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

Ik hoop dat dit nuttig was!


Antwoord 4, autoriteit 3%

Serializer optieszijn samengevoegd in ActiveModel Serializers en zijn nu beschikbaar (sinds 0.10 ).


Antwoord 5

Overschrijven is een goed idee, maar als u de supergebruikt, worden de kenmerken berekend voordat u verwijdert wat u wilt. Als het voor jou geen verschil maakt, oké, maar als dat wel het geval is, kun je het gebruiken:

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


Antwoord 6

Hier leest u hoe u parameters rechtstreeks aan de serializer-instantie kunt doorgeven en kenmerken toonof verbergtop basis van deze parameters in de serializer-declaratie.

Het werkt ook met serializers voor ouder en kind.

Controller of parent-serializer:

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

Serializer met voorwaarden:

class PublicLocationSerializer < ActiveModel::Serializer
  attributes :id, :latitude, :longitude, :title
  def title
    object.title if @instance_options[:params][:show_title]
  end
end

Other episodes