首页 文章

as_json没有在关联上调用as_json

提问于
浏览
35

我有一个模型,其数据在呈现为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> d = Dog.first =>#<Dog id:1,owner_id:1,名称:“Scooby”,秘密:“我喜欢拐杖无处不在“> 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)Owner :: as_json => {“owner”=> {“id”=> 1,“name”= >“Shaggy”,:dog => {“id”=> 1,“name”=>“Scooby”,“owner_id”=> 1,“secret”=>“我喜欢在任何地方徘徊”}}}

谢谢您的帮助

6 回答

  • 1

    我遇到了同样的问题 . 我希望这个工作:

    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 %>
    

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

  • 0

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

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

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

  • 2

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

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

    所以这里's a workaround which doesn' t需要一个补丁,适用于大多数简单的情况 . 这适用于您想要调用的关联的 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
    

    如果您遵循指南,无论何时 as_json() 方法中的关联,您都需要将所需的任何选项定义为要引用的模型中的常量,这适用于任意级别的关联 . NOTE 我只需要在上面的例子中定制的第一级关联 .

  • 8

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

    我一直都是 frustrated with passing a complex set of options 来创建我想要的JSON视图 . 您在Rails 3.0.9中使用Mongoid时遇到的问题促使我编写了JSON模板 . 但实际上,如果你正在处理关系或自定义api属性,事实证明 templates are way nicer.

    此外,处理不同的输出对我来说就像是View层,所以 I settled on using RABL, the API templating language. 这使得构建有效的JSON并包含任何关联或字段变得非常容易 .

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

相关问题