如何在Rails中重写为_json?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (13)

这个问题没有得到适当的探索。真正的问题在于render :json

原始问题中的第一个代码粘贴将产生预期的结果。但是,仍然有一个警告。看到这个例子:

render :json => current_user

一样的

render :json => current_user.to_json

也就是说,render :json不会自动调用to_json与用户对象关联的方法。实际上,如果to_jsonUser模型上被重写,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

这一切对我来说都很愚蠢。这似乎告诉我,当指定type时render实际上没有调用。有人能解释这里发生了什么吗?Model#to_json:json

我已经看到了一些其他的例子,但我没有做我想要的。

我尝试着:

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)进去了

/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散列覆盖。

def to_json(options)
  ...
end

的更详细的解释to_jsonas_json和渲染:

在ActiveSupport 2.3.3中,as_json增加了解决您遇到的问题。json 的创建应该与json的渲染分开。

现在,随时to_json调用一个对象,as_json被调用来创建数据结构,然后该哈希被编码为JSON字符串ActiveSupport::json.encode。这发生在所有类型上:对象,数字,日期,字符串等(请参阅ActiveSupport代码)。

ActiveRecord对象的行为方式相同。有一个默认as_json实现会创建一个包含所有模型属性的散列。您应该as_json在模型中重写以创建所需的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如上所述触发。

所以,只要你的模型被as_json覆盖(或不),你的控制器代码显示一个模型应该看起来像这样:

format.json { render :json => @user }

故事的寓意是:避免to_json直接调用,允许render为你这样做。如果需要调整JSON输出,请调用as_json

format.json { render :json => 
    @user.as_json(:only => [:username], :methods => [:avatar]) }
用户回答回答于

如果你在Rails 3中遇到这个问题,可以重写serializable_hash而不是as_json。这将免费得到XML格式

扫码关注云+社区