Ruby-on-rails 活动模型序列化程序中的条件属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29705802/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Conditional attributes in Active Model Serializers
提问by Dan
How do I render an attribute only if some condition is true?
仅当某些条件为真时如何呈现属性?
For example, I want to render User's token attribute on create action.
例如,我想在创建操作上呈现用户的令牌属性。
回答by Abdelhakim AKODADI
You can also do it this way:
你也可以这样做:
class EntitySerializer < ActiveModel::Serializer
attributes :id, :created_at, :updated_at
attribute :conditional_attr, if: :condition?
def condition?
#condition code goes here
end
end
For example:
例如:
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 (Suggested by Joe Essey) :
编辑(由Joe Essey建议):
This method doesn't work with latest version (0.10)
此方法不适用于最新版本 ( 0.10)
With the version 0.8it is even simpler. You don't have to use the if: :condition?. Instead you can use the following convention to achieve the same result.
有了这个版本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
The example above would look like this.
上面的例子看起来像这样。
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
See 0.8 documentationfor more details.
有关更多详细信息,请参阅0.8 文档。
回答by apneadiving
you can override the attributesmethod, here is a simple example:
您可以覆盖该attributes方法,这是一个简单的示例:
class Foo < ActiveModel::Serializer
attributes :id
def attributes(*args)
hash = super
hash[:last_name] = 'Bob' unless object.persisted?
hash
end
end
回答by froskos
You could start by setting a condition on the serializers 'initialize' method. This condition can be passed from wherever else in your code, included in the options hash that 'initialize' accepts as second 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
In this case attr1 would always be passed, while the conditional attributes would be hidden if the condition is true.
在这种情况下,attr1 将始终被传递,而如果条件为真,则条件属性将被隐藏。
You would get the result of this custom serialization wherever else in your code as follows:
您将在代码中的其他任何位置获得此自定义序列化的结果,如下所示:
custom_serialized_object = SomeCustomSerializer.new(object_to_serialize, {:condition => true})
I hope this was useful!
我希望这是有用的!
回答by Dan
回答by Passalini
Override is a good idea, but if you use the superthe attributes will be calculated before you remove what you want. If it does not make difference to you, ok, but when it does, you can use it:
覆盖是一个好主意,但如果您使用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
ps:v0.10.0.rc3

