as_json没有在关联上调用as_json

nan*_*pus 35 json ruby-on-rails ruby-on-rails-3

我有一个模型,其中数据在呈现为json时永远不应包含在内.所以我实现了类'as_json方法以适当地运行.问题是当与此模型关联的其他模型呈现json时,我的自定义as_json未被调用.

class Owner < ActiveRecord::Base
  has_one :dog

  def as_json(options={})
    puts "Owner::as_json"
    super(options)
  end  
end

class Dog < ActiveRecord::Base
  belongs_to :owner

  def as_json(options={})
    puts "Dog::as_json"
    options[:except] = :secret
    super(options)
  end  
end
Run Code Online (Sandbox Code Playgroud)

加载开发环境(Rails 3.0.3)
ruby-1.9.2-p136:001> d = Dog.first
= #<Dog id: 1, owner_id: 1, name: "Scooby", secret: "I enjoy crapping everwhere">>
ruby-1.9.2-p136:002> d.as_json
Dog :: as_json
=> {"dog" => {"id"=> 1,"name"=>"Scooby","owner_id"=> 1}}
ruby-1.9.2-p136:004> d.owner.as_json(:include =>:dog)
所有者:: as_json
=> {"owner"=> {"id"=> 1,"name"=>"Shaggy",:dog => {"id"=> 1,"name"=>"Scooby", "owner_id"=> 1,"秘密"=>"我喜欢疯狂到处"}}}}

谢谢您的帮助

Joh*_*ohn 21

这是Rails中的已知错误.(由于从之前的错误跟踪器迁移到Github问题,该问题被标记为已关闭,但从Rails 3.1开始仍然是一个问题.)


sha*_*xxv 9

如上所述,这是Rails基础的一个问题.轨道补丁这里还没有应用,似乎至少稍有争议,所以我犹豫本地应用它.即使应用为猴子补丁,也可能使未来的铁路升级变得复杂化.

我还在考虑上面建议的RABL,它看起来很有用.目前,我宁愿不在我的应用中添加另一种视图模板语言.我目前的需求非常小.

所以这是一个解决方法,它不需要补丁,适用于大多数简单的情况.这适用于as_json你想要调用的关联方法

def as_json(options={})
  super( <... custom options ...> )
end
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我有很多Schedule模型Events

class Event < ActiveRecord::Base

  # define json options as constant, or you could return them from a method
  EVENT_JSON_OPTS = { :include => { :locations => { :only => [:id], :methods => [:name] } } }

  def as_json(options={})
    super(EVENT_JSON_OPTS)
  end
end

class Schedule < ActiveRecord::Base
  has_many :events

  def as_json(options={})
    super(:include => { :events => { Event::EVENT_JSON_OPTS } })
  end
end
Run Code Online (Sandbox Code Playgroud)

如果您遵循指南,只要您:includeas_json()方法中建立关联,就可以将所需的任何选项定义为要引用的模型中的常量,这适用于任意级别的关联.注意我只需要在上面的例子中定制的第一级关联.


Sno*_*man 5

我发现serializable_hash的工作原理与您期望的as_json一样,并且始终被称为:

  def serializable_hash(options = {})
    result = super(options)
    result[:url] = "http://.."
    result
  end
Run Code Online (Sandbox Code Playgroud)