Ruby on rails 将虚拟属性添加到json输出
假设我有一个处理待办事项列表的应用程序。该列表包含已完成和未完成的项目。现在我想向列表对象添加两个虚拟属性;列表中已完成和未完成项目的计数。我还需要在json输出中显示这些内容 我的模型中有两种方法用于获取未完成/已完成的项目:Ruby on rails 将虚拟属性添加到json输出,ruby-on-rails,json,Ruby On Rails,Json,假设我有一个处理待办事项列表的应用程序。该列表包含已完成和未完成的项目。现在我想向列表对象添加两个虚拟属性;列表中已完成和未完成项目的计数。我还需要在json输出中显示这些内容 我的模型中有两种方法用于获取未完成/已完成的项目: def unfinished_items self.items.where("status = ?", false) end def finished_items self.items.where("status = ?", true) end 那
def unfinished_items
self.items.where("status = ?", false)
end
def finished_items
self.items.where("status = ?", true)
end
那么,如何在json输出中获得这两个方法的计数呢
我正在使用Rails 3.1,Rails中对象的序列化有两个步骤:
- 首先,调用
将对象转换为简化的散列as_json
- 然后,在
返回值上调用as_json
,以获取最终的json字符串to_json
单独留给_json
,因此您所需要做的就是添加如下内容:
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
您也可以这样做:
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,请查看。另一种方法是将其添加到您的模型中:
def attributes
super.merge({'unfinished' => unfinished_items, 'finished' => finished_items})
end
这也将自动适用于xml序列化。
但是请注意,您可能希望使用字符串作为键,因为在rails 3中对键进行排序时,该方法无法处理符号。但是它在rails 4中没有排序,所以应该不会再有问题了。对于rails 4,您可以执行以下操作-
render json: @my_object.to_json(:methods => [:finished_items, :unfinished_items])
希望这有助于更新/最新版本的用户我只是想为像我这样的人提供这个答案,他们试图将此集成到现有的as_json块中:
def as_json(options={})
super(:only => [:id, :longitude, :latitude],
:include => {
:users => {:only => [:id]}
}
).merge({:premium => premium?})
只需将
.merge({})
添加到super()的末尾
只需将所有数据关闭为一个散列,如
render json:{items:items,finished:finished,unfinished:unfinished}
这就可以了,而不必做一些难看的重写。例如,如果您有一个型号列表
,您可以将其放入控制器中:
render json: list.attributes.merge({
finished_items: list.finished_items,
unfinished_items: list.unfinished_items
})
如上所述,:methods
将允许您将特定模型的方法/函数作为json属性返回,如果您有复杂的关联,这将起到作用,因为它将向现有模型/关联添加函数:D如果您不想将重新定义为\u json
检查此代码,请注意我是如何使用:methods
以及:include
[N+查询甚至不是一个选项;)]
render json:@YOUR_MODEL.to_json(:methods=>[:method_1,:method_2],:include=>[:company,:surveys,:customer=>{:include=>[:user]}])
在这种情况下,将改写为_json
函数将更加困难(特别是因为您必须手动添加:include
关联:/
def as_json(选项={})
结束
如果要渲染具有虚拟属性的对象数组,可以使用
render json: many_users.as_json(methods: [:first_name, :last_name])
其中
first_name
和last_name
是在您的模型上定义的虚拟属性我没有尝试过这一点:也许您所要做的就是添加属性读取器:finished_items?我在最上面的一个错误中得到了这个错误:nil:NilClass的未定义方法merge',因此我将其替换为选项。merge`with(选项|{}).merge
@Turadg:由于默认的选项={},第一个应该可以工作
除非有人在某处传递一个显式的nil
,否则为了安全起见,我将修补额外的偏执狂。抱歉,您的评论在每天的混乱中丢失了,所以我回您电话有点晚。这也是确保在呈现关联对象和使用include: (我用它来解决使用attr_加密gem的问题)