未正确探讨此问题。真正的问题在于render :json。
render :json
原始问题中的第一个代码粘贴将产生预期的结果。但是,仍然需要注意。请参阅以下示例:
render :json => current_user
是 不 一样的
render :json => current_user.to_json
也就是说,render :json不会自动调用to_json与User对象关联的方法。 实际上 ,如果to_json在User模型上被覆盖,render :json => @user将生成以下ArgumentError描述。
to_json
User
render :json => @user
ArgumentError
# works if User#to_json is not overridden render :json => current_user # If User#to_json is overridden, User requires explicit call render :json => current_user.to_json
这一切对我来说似乎很愚蠢。这似乎是在告诉我在指定类型时render实际上并没有在调用。有人可以解释这里的实际情况吗?Model#to_json``:json
render
Model#to_json``:json
任何可以帮助我解决这个问题的精灵都可以回答我的另一个问题:[如何通过在Rails中组合@ foo.to_json(options)和@bars.to_json(options)来构建JSON响应
我在SO上看到了其他一些示例,但是我没有做我想要的事情。
我尝试着:
class User < ActiveRecord::Base # this actually works! (see update summary above) def to_json super(:only => :username, :methods => [:foo, :bar]) end end
我ArgumentError: wrong number of arguments (1 for 0)进去了
ArgumentError: wrong number of arguments (1 for 0)
/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json
有任何想法吗?
你得到ArgumentError: wrong number of arguments (1 for 0),因为to_json需要重写一个参数的options哈希值。
options
def to_json(options) ... end
的更详细的解释to_json,as_json和渲染:
as_json
在ActiveSupport 2.3.3中,as_json添加了解决您遇到的问题的方法。json 的 创建 应与json的 呈现 分开。
现在,随时to_json可以在对象as_json上调用,调用来创建数据结构,然后使用将该哈希编码为JSON字符串ActiveSupport::json.encode。所有类型均会发生这种情况:对象,数字,日期,字符串等(请参阅ActiveSupport代码)。
ActiveSupport::json.encode
ActiveRecord对象的行为方式相同。有一个默认as_json实现,该实现创建一个包含所有模型属性的哈希。 您应该as_json在Model中重写以创建所需的JSON结构。as_json,就像旧的一样to_json,采用选项哈希,您可以在其中指定要声明式包含的属性和方法。
def as_json(options) # this example ignores the user's options super(:only => [:email, :handle]) end
在您的控制器中,render :json => o可以接受字符串或对象。 如果是字符串,则将其作为响应主体传递,如果是对象,则将其作为响应主体to_json进行调用,并as_json如上所述触发。
render :json => o
因此,只要您的模型正确地用as_json覆盖(或不覆盖)表示,那么用于显示一个模型的控制器代码应如下所示:
format.json { render :json => @user }
这个故事的寓意是: 避免to_json直接打电话,允许render为您这样做。如果您需要调整JSON输出,请致电as_json。
format.json { render :json => @user.as_json(:only => [:username], :methods => [:avatar]) }