从MongoMapper对象中包含JSON响应中的嵌套对象

时间:2011-02-24 17:19:48

标签: ruby-on-rails json mongomapper responders

class Api::StoresController < ApplicationController  
  respond_to :json

  def index
    @stores = Store.all(:include => :products)
    respond_with @stores
  end
end

仅返回没有产品的商店,

Store.find(:all).to_json(:include => :products)

关联已经过测试,我可以在控制台中看到嵌套产品,比如说,

Store.first.products

将这些产品包含在MongoMapper中的正确方法是什么?

以下是我的模特:

   class Store
     include MongoMapper::Document         
     many :products, :foreign_key => :store_ids 
   end

   class Product
     include MongoMapper::Document         
     key :store_ids, Array, :typecast => 'ObjectId'
     many :stores, :in => :store_ids
   end

更新

在尝试Scott的建议时,我已将以下内容添加到商店模型中:

def self.all_including_nested
  stores = []
  Store.all.each do |store|
    stores << store.to_hash
  end
end

def to_hash
  keys = self.key_names
  hash = {}
  keys.each{|k| hash[k] = self[k]}
  hash[:products] = self.products
  hash[:services] = self.services
  hash
end

在控制器中:

def index
  @stores = Store.all_including_nested
  respond_with @stores
end

哪些看起来它应该有效?假设哈希数组会在其上调用#to_json,那么每个哈希和每个产品+服务都会发生相同的情况。我正在阅读ActiveSupport :: JSON的源代码,到目前为止,这是我从中学到的东西。

但是,还没有工作...... :(

2 个答案:

答案 0 :(得分:17)

查看as_json()方法。你把它放在你的模型中,定义你的json,然后简单地调用render :json方法并得到你想要的。

class Something
  def as_json(options={})
    {:account_name       => self.account_name,
     :expires_on         => self.expires_on.to_s,
     :collections        => self.collections,
     :type               => "Institution"}
  end
end

你会注意到self.collections这是一种很多关系。该模型还定义了as_json()

class Collection
  def as_json(options={})
    {:name          => self.name,
     :title         => self.title,
     :isbn          => self.isbn,
     :publisher     => self.publisher,
     :monthly_views => self.monthly_views}
  end
end

这个包含self.monthly_views,代表另一种关系。

然后在你的控制器中:

@somethings = Something.all
render :json => @somethings

答案 1 :(得分:2)

您可能必须创建自己的方法来生成哈希,然后将哈希转换为JSON。我在想这样的事情:

store = Store.first
keys = store.key_names
hash = {}
keys.each{|k| hash[k] = store[k]}
hash[:products] = store.products
hash.to_json