如何构建由多个模型的Rails的JSON响应 [英] How to build a JSON response made up of multiple models in Rails

查看:166
本文介绍了如何构建由多个模型的Rails的JSON响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,将所需的结果

我有用户项目模型。我想建立一个JSON响应,看起来像这样:

  {
  用户:
    {用户名:鲍勃,富:无论,酒吧:你好!},

  项目:
    {ID:1,名:一,ZIM:行星,吉尔:土},
    {ID:2,名:二,ZIM:行星,吉尔:火星}
  ]
}
 

不过,我的用户项目模式比只是那些更多的属性。我找到了一种方法来得到这个工作,但提防,它不是pretty的...请帮助...

更新

接下来的部分包含了原来的问题。最后一节显示了新的解决方案。


我的黑客

home_controller.rb

 类的HomeController<的ApplicationController

  DEF观察
    respond_to代码做|格式|
      format.js {渲染:JSON => Observation.new(CURRENT_USER,@items).to_json}
    结束
  结束

结束
 

observation.rb

 #注:这是不是的ActiveRecord的子类::基地
#这个类只是充当一个容器聚合所有可观察的对象
课堂观察
  attr_accessor:用户:项目

  高清初始化(用户资料)
    self.user =用户
    self.items =项目
  结束

  #的JSON必须是在它之前发送到`to_json`方法在home_controller否则JSON将被转义德codeD ...
  # 真是一团糟!
  高清to_json
    {
      :用户=>的ActiveSupport :: JSON.de code(user.to_json(:只=>:用户名:方法=> [:foo,那么:巴])),
      :项目=>的ActiveSupport :: JSON.de code(auctions.to_json(:只=> [:ID,:姓名]:方法=> [:ZIM,:GIR]))
    }
  结束
结束
 


看马!没有更多的黑客!

覆盖 as_json 而不是

的<一个href="http://api.rubyonrails.org/classes/ActiveRecord/Serialization.html#M001874">ActiveRecord::Serialization#as_json文档是pretty的稀疏。下面是简单的:

  as_json(选项=无)
  [节目源]
 

有关 to_json VS as_json 的详细信息,请参阅的Overriding to_json 2.3.5

的code SANS黑客

user.rb

 类用户的LT;的ActiveRecord :: Base的

  高清as_json(选项)
    选项​​= {:只=&GT; [:用户名]:方法=&GT; [:foo,那么:巴]} .merge(选项)
    超(选项)
  结束

结束
 

item.rb的

 类项目&lt;的ActiveRecord :: Base的

  高清as_json(选项)
    选项​​= {:只=&GT; [:ID,名称]:方法=&GT; [:ZIM,:GIR]} .merge(选项)
    超(选项)
  结束

结束
 

home_controller.rb

 类的HomeController&LT;的ApplicationController

  DEF观察
    @items = Items.find(...)
    respond_to代码做|格式|
      format.js做
        渲染:JSON =&GT; {
          :用户=&GT; CURRENT_USER || {},
          :项目=&GT; @items
        }
      结束
    结束
  结束

结束
 

解决方案

EDITED 使用 as_json 而不是 to_json 。请参阅<一href="http://stackoverflow.com/questions/2572284/override-to-json-in-rails-2-3-5/2574900">http://stackoverflow.com/questions/2572284/override-to-json-in-rails-2-3-5/2574900对于详细的解释。我觉得这是最好的答案。

可以呈现在控制器所需的JSON,而不需要辅助模型

 高清观察
  respond_to代码做|格式|
    format.js做
      渲染:JSON =&GT; {
        :用户=&GT; current_user.as_json(:只=&GT; [:用户名]:方法=&GT; [:foo,那么:巴]),
        :项目=&GT; @ items.collect {| I | i.as_json(:只=&GT; [:ID,:姓名]:方法=&GT; [:ZIM,:GIR])}
      }
    结束
  结束
结束
 

确认的ActiveRecord :: Base.include_root_in_json 设置为false,否则你会得到一个'用户'属性'用户'的内部。不幸的是,它看起来像阵列不通过选项到每一个元素,因此收集是必要的。

First, the desired result

I have User and Item models. I'd like to build a JSON response that looks like this:

{
  "user":
    {"username":"Bob!","foo":"whatever","bar":"hello!"},

  "items": [
    {"id":1, "name":"one", "zim":"planet", "gir":"earth"},
    {"id":2, "name":"two", "zim":"planet", "gir":"mars"}
  ]
}

However, my User and Item model have more attributes than just those. I found a way to get this to work, but beware, it's not pretty... Please help...

Update

The next section contains the original question. The last section shows the new solution.


My hacks

home_controller.rb

class HomeController < ApplicationController

  def observe
    respond_to do |format|
      format.js { render :json => Observation.new(current_user, @items).to_json }
    end
  end

end

observation.rb

# NOTE: this is not a subclass of ActiveRecord::Base
# this class just serves as a container to aggregate all "observable" objects
class Observation
  attr_accessor :user, :items

  def initialize(user, items)
    self.user = user
    self.items = items
  end

  # The JSON needs to be decoded before it's sent to the `to_json` method in the home_controller otherwise the JSON will be escaped...
  # What a mess!
  def to_json
    {
      :user => ActiveSupport::JSON.decode(user.to_json(:only => :username, :methods => [:foo, :bar])),
      :items => ActiveSupport::JSON.decode(auctions.to_json(:only => [:id, :name], :methods => [:zim, :gir]))
    }
  end
end


Look Ma! No more hacks!

Override as_json instead

The ActiveRecord::Serialization#as_json docs are pretty sparse. Here's the brief:

as_json(options = nil) 
  [show source]

For more information on to_json vs as_json, see the accepted answer for Overriding to_json in Rails 2.3.5

The code sans hacks

user.rb

class User < ActiveRecord::Base

  def as_json(options)
    options = { :only => [:username], :methods => [:foo, :bar] }.merge(options)
    super(options)
  end

end

item.rb

class Item < ActiveRecord::Base

  def as_json(options)
    options = { :only => [:id, name], :methods => [:zim, :gir] }.merge(options)
    super(options)
  end

end

home_controller.rb

class HomeController < ApplicationController

  def observe
    @items = Items.find(...)
    respond_to do |format|
      format.js do
        render :json => {
          :user => current_user || {},
          :items => @items
        }
      end
    end
  end

end

解决方案

EDITED to use as_json instead of to_json. See http://stackoverflow.com/questions/2572284/override-to-json-in-rails-2-3-5/2574900 for a detailed explanation. I think this is the best answer.

You can render the JSON you want in the controller without the need for the helper model.

def observe
  respond_to do |format|
    format.js do
      render :json => {
        :user => current_user.as_json(:only => [:username], :methods => [:foo, :bar]),
        :items => @items.collect{ |i| i.as_json(:only => [:id, :name], :methods => [:zim, :gir]) }
      }
    end
  end
end

Make sure ActiveRecord::Base.include_root_in_json is set to false or else you'll get a 'user' attribute inside of 'user'. Unfortunately, it looks like Arrays do not pass options down to each element, so the collect is necessary.

这篇关于如何构建由多个模型的Rails的JSON响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆