假设我有一个处理TODO列表的应用程序。该清单已完成和未完成的项目。现在我想向列表对象添加两个虚拟属性;列表中已完成和未完成的项目数。我还需要在json输出中显示它们。
我的模型中有两个方法可以获取未完成/已完成的项目:
def unfinished_items
self.items.where("status = ?", false)
end
def finished_items
self.items.where("status = ?", true)
end
那么,我怎样才能在json输出中得到这两个方法的计数?
我正在使用Rails 3.1
答案 0 :(得分:107)
Rails中对象的序列化有两个步骤:
as_json
将对象转换为简化的哈希。to_json
返回值上调用as_json
以获取最终的JSON字符串。您通常希望单独留下to_json
,这样您只需添加your own as_json
implementation,就像这样:
def as_json(options = { })
# just in case someone says as_json(nil) and bypasses
# our default...
super((options || { }).merge({
:methods => [:finished_items, :unfinished_items]
}))
end
你也可以这样做:
def as_json(options = { })
h = super(options)
h[:finished] = finished_items
h[:unfinished] = unfinished_items
h
end
如果您想为方法支持的值使用不同的名称。
如果您关心XML和JSON,请查看serializable_hash
。
答案 1 :(得分:27)
使用Rails 4,您可以执行以下操作 -
render json: @my_object.to_json(:methods => [:finished_items, :unfinished_items])
希望这可以帮助那些处于后期/最新版本的人
答案 2 :(得分:15)
另一种方法是将此添加到您的模型中:
def attributes
super.merge({'unfinished' => unfinished_items, 'finished' => finished_items})
end
这也可以自动用于xml序列化。 http://api.rubyonrails.org/classes/ActiveModel/Serialization.html 但请注意,您可能需要为键使用字符串,因为在对rails 3中的键进行排序时,该方法无法处理符号。但它不会在rails 4中排序,因此不应再出现问题。
答案 3 :(得分:3)
将所有数据关闭到一个哈希,例如
render json: {items: items, finished: finished, unfinished: unfinished}
答案 4 :(得分:1)
我只是觉得我会为像我这样的人提供这个答案,他试图将其整合到现有的 as_json 块中:
def as_json(options={})
super(:only => [:id, :longitude, :latitude],
:include => {
:users => {:only => [:id]}
}
).merge({:premium => premium?})
将.merge({})
放在super()
答案 5 :(得分:1)
如上面列出的Aswin,:methods
将使您能够将特定模型的方法/函数作为json属性返回,如果您有复杂的关联,这将会起到作用,因为它将添加函数现有的模型/对象:如果您不想重新定义as_json
检查此代码,请注意我如何使用:methods
以及:include
[N +查询甚至不是一个选项;)
render json: @YOUR_MODEL.to_json(:methods => [:method_1, :method_2], :include => [:company, :surveys, :customer => {:include => [:user]}])
在这种情况下,覆盖as_json
功能将更加困难(特别是因为您必须手动添加:include
点击:/
def as_json(options = { })
end
答案 6 :(得分:0)
这样做,而不必做一些丑陋的覆盖。例如,如果你有一个模型(12,6,6) -> 1
(1,0,6) -> 1
(2,3,7) -> 0
,你可以把它放在你的控制器中:
List
答案 7 :(得分:0)
如果你想用它们的虚拟属性渲染一组对象,你可以使用
render json: many_users.as_json(methods: [:first_name, :last_name])
其中 first_name
和 last_name
是定义在模型上的虚拟属性