如何构建由多个模型的Rails的JSON响应 [英] How to build a JSON response made up of multiple models in Rails
问题描述
首先,将所需的结果
我有用户
和项目
模型。我想建立一个JSON响应,看起来像这样:
{
用户:
{用户名:鲍勃,富:无论,酒吧:你好!},
项目:
{ID:1,名:一,ZIM:行星,吉尔:土},
{ID:2,名:二,ZIM:行星,吉尔:火星}
]
}
不过,我的用户
和项目
模式比只是那些更多的属性。我找到了一种方法来得到这个工作,但提防,它不是pretty的...请帮助...
更新
接下来的部分包含了原来的问题。最后一节显示了新的解决方案。
我的黑客
home_controller.rb
类的HomeController<的ApplicationController
DEF观察
respond_to代码做|格式|
format.js {渲染:JSON => Observation.new(CURRENT_USER,@items).to_json}
结束
结束
结束
observation.rb
#注:这是不是的ActiveRecord的子类::基地
#这个类只是充当一个容器聚合所有可观察的对象
课堂观察
attr_accessor:用户:项目
高清初始化(用户资料)
self.user =用户
self.items =项目
结束
#的JSON必须是在它之前发送到`to_json`方法在home_controller否则JSON将被转义德codeD ...
# 真是一团糟!
高清to_json
{
:用户=>的ActiveSupport :: JSON.de code(user.to_json(:只=>:用户名:方法=> [:foo,那么:巴])),
:项目=>的ActiveSupport :: JSON.de code(auctions.to_json(:只=> [:ID,:姓名]:方法=> [:ZIM,:GIR]))
}
结束
结束
看马!没有更多的黑客!
覆盖 as_json
而不是
的<一个href="http://api.rubyonrails.org/classes/ActiveRecord/Serialization.html#M001874">ActiveRecord::Serialization#as_json文档是pretty的稀疏。下面是简单的:
as_json(选项=无)
[节目源]
有关 to_json
VS as_json
的详细信息,请参阅的Overriding to_json 2.3.5
的code SANS黑客
user.rb
类用户的LT;的ActiveRecord :: Base的
高清as_json(选项)
选项= {:只=&GT; [:用户名]:方法=&GT; [:foo,那么:巴]} .merge(选项)
超(选项)
结束
结束
item.rb的
类项目&lt;的ActiveRecord :: Base的
高清as_json(选项)
选项= {:只=&GT; [:ID,名称]:方法=&GT; [:ZIM,:GIR]} .merge(选项)
超(选项)
结束
结束
home_controller.rb
类的HomeController&LT;的ApplicationController
DEF观察
@items = Items.find(...)
respond_to代码做|格式|
format.js做
渲染:JSON =&GT; {
:用户=&GT; CURRENT_USER || {},
:项目=&GT; @items
}
结束
结束
结束
结束
EDITED 使用 as_json
而不是 to_json
。请参阅<一href="http://stackoverflow.com/questions/2572284/override-to-json-in-rails-2-3-5/2574900">http://stackoverflow.com/questions/2572284/override-to-json-in-rails-2-3-5/2574900对于详细的解释。我觉得这是最好的答案。
可以呈现在控制器所需的JSON,而不需要辅助模型
高清观察
respond_to代码做|格式|
format.js做
渲染:JSON =&GT; {
:用户=&GT; current_user.as_json(:只=&GT; [:用户名]:方法=&GT; [:foo,那么:巴]),
:项目=&GT; @ items.collect {| I | i.as_json(:只=&GT; [:ID,:姓名]:方法=&GT; [:ZIM,:GIR])}
}
结束
结束
结束
确认的ActiveRecord :: Base.include_root_in_json
设置为false,否则你会得到一个'用户'属性'用户'的内部。不幸的是,它看起来像阵列不通过选项
到每一个元素,因此收集
是必要的。
First, the desired result
I have User
and Item
models. I'd like to build a JSON response that looks like this:
{
"user":
{"username":"Bob!","foo":"whatever","bar":"hello!"},
"items": [
{"id":1, "name":"one", "zim":"planet", "gir":"earth"},
{"id":2, "name":"two", "zim":"planet", "gir":"mars"}
]
}
However, my User
and Item
model have more attributes than just those. I found a way to get this to work, but beware, it's not pretty... Please help...
Update
The next section contains the original question. The last section shows the new solution.
My hacks
home_controller.rb
class HomeController < ApplicationController
def observe
respond_to do |format|
format.js { render :json => Observation.new(current_user, @items).to_json }
end
end
end
observation.rb
# NOTE: this is not a subclass of ActiveRecord::Base
# this class just serves as a container to aggregate all "observable" objects
class Observation
attr_accessor :user, :items
def initialize(user, items)
self.user = user
self.items = items
end
# The JSON needs to be decoded before it's sent to the `to_json` method in the home_controller otherwise the JSON will be escaped...
# What a mess!
def to_json
{
:user => ActiveSupport::JSON.decode(user.to_json(:only => :username, :methods => [:foo, :bar])),
:items => ActiveSupport::JSON.decode(auctions.to_json(:only => [:id, :name], :methods => [:zim, :gir]))
}
end
end
Look Ma! No more hacks!
Override as_json
instead
The ActiveRecord::Serialization#as_json docs are pretty sparse. Here's the brief:
as_json(options = nil)
[show source]
For more information on to_json
vs as_json
, see the accepted answer for Overriding to_json in Rails 2.3.5
The code sans hacks
user.rb
class User < ActiveRecord::Base
def as_json(options)
options = { :only => [:username], :methods => [:foo, :bar] }.merge(options)
super(options)
end
end
item.rb
class Item < ActiveRecord::Base
def as_json(options)
options = { :only => [:id, name], :methods => [:zim, :gir] }.merge(options)
super(options)
end
end
home_controller.rb
class HomeController < ApplicationController
def observe
@items = Items.find(...)
respond_to do |format|
format.js do
render :json => {
:user => current_user || {},
:items => @items
}
end
end
end
end
EDITED to use as_json
instead of to_json
. See http://stackoverflow.com/questions/2572284/override-to-json-in-rails-2-3-5/2574900 for a detailed explanation. I think this is the best answer.
You can render the JSON you want in the controller without the need for the helper model.
def observe
respond_to do |format|
format.js do
render :json => {
:user => current_user.as_json(:only => [:username], :methods => [:foo, :bar]),
:items => @items.collect{ |i| i.as_json(:only => [:id, :name], :methods => [:zim, :gir]) }
}
end
end
end
Make sure ActiveRecord::Base.include_root_in_json
is set to false or else you'll get a 'user' attribute inside of 'user'. Unfortunately, it looks like Arrays do not pass options
down to each element, so the collect
is necessary.
这篇关于如何构建由多个模型的Rails的JSON响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!