as_json没有在关联上调用as_json

时间:2011-01-30 03:28:43

标签: ruby-on-rails json 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
  

加载开发环境(Rails 3.0.3)
  ruby-1.9.2-p136:001&gt; d = Dog.first
    =&GT; #<Dog id: 1, owner_id: 1, name: "Scooby", secret: "I enjoy crapping everwhere"&GT;
  ruby-1.9.2-p136:002&gt; d.as_json
  狗:: as_json
   =&GT; {“dog”=&gt; {“id”=&gt; 1,“name”=&gt;“Scooby”,“owner_id”=&gt; 1}}
  ruby-1.9.2-p136:004&gt; d.owner.as_json(:include =&gt;:dog)
  业主:: as_json
   =&GT; {“owner”=&gt; {“id”=&gt; 1,“name”=&gt;“Shaggy”,:dog =&gt; {“id”=&gt; 1,“name”=&gt;“Scooby”, “owner_id”=&gt; 1,“秘密”=&gt;“我喜欢疯狂的地方”}}}}

感谢您的帮助

6 个答案:

答案 0 :(得分:21)

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

答案 1 :(得分:8)

如上所述,这是Rails基础的一个问题。 rails patch here尚未应用,似乎至少有点争议,所以我对在本地应用它犹豫不决。即使应用为猴子补丁,也可能使未来的铁路升级变得复杂。

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

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

def as_json(options={})
  super( <... custom options ...> )
end

就我而言,我的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

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

答案 2 :(得分:2)

我遇到了同样的问题。我想要这个工作:

render :json => @favorites.as_json(:include => :location)

但事实并非如此,我最终添加了一个index.json.erb,其中包含以下内容:

<% favs = @favorites.as_json.each do |fav| %>
    <% fav["location"] = Location.find(fav["location_id"]).as_json %>
<% end %>
<%= favs.to_json.html_safe %>

不是解决方法 - 只是一个解决方法。我想你也做了同样的事情。

答案 3 :(得分:2)

我发现serializable_hash就像你期望as_json一样工作,并且总是被调用:

  def serializable_hash(options = {})
    result = super(options)
    result[:url] = "http://.."
    result
  end

答案 4 :(得分:1)

更新 @John指出这是Rails中的已知错误。修复它的补丁似乎是:https://github.com/rails/rails/pull/2200。不过,你可以试试RABL,因为它很甜。

我总是因为传递一组复杂的选项而感到沮丧来创建我想要的JSON视图。您在Rails 3.0.9中使用Mongoid时遇到的问题促使我编写了JSON模板。但实际上,如果你正在处理关系或自定义api属性,那么模板就更好了。

此外,处理不同的输出对我来说就像是View层,所以我决定使用API​​模板语言RABL这使得构建有效的JSON非常容易。包括任何协会或领域。

不是问题的解决方案,而是用例的更好解决方案。

答案 5 :(得分:0)