2013-10-26 107 views
0

我有一個Item類也包含很多項目(使用has_many)。我想要做的是讀取所有沒有父項(頂層)的項目及其所有子項目。所以基本上我需要將我的整個Item表正確嵌套到json中。Rails to_json與所有關係

這是我現在正在使用的代碼,但這隻返回最高級別的項目和它們的項目,它不會低於此值。 (所以我只剩下兩個級別)

@items = Item.where("item_id IS ?" , nil).order("position") 
respond_to do |format| 
    format.json { render :json => @items.to_json(:include => :items)} 
end 
+0

你知道Rabl的寶石?我認爲你可以使用它。 https://github.com/nesquena/rabl –

+0

物品類也包含很多物品? – shiva

+0

@shiva是的。所以基本上每個項目我都可以做Item.first.items – networkprofile

回答

2

不建議覆蓋as_json或to_json

原因是你需要其他地方的原始數據,你可能需要其他格式的數據。操縱as_json將最終更改數據,並且您無法擴展。

使用裝飾器是要走的路。一個不錯的選擇寶石ActiveModel Serializers。基本上,它像這樣工作

class ItemSerializer < ActiveModel::Serializer 
    attributes :id, :title, :body 
    has_many :comments # The JSON output will have comments inside. 
end 

然後在你的控制器:

@items = Item.where("item_id IS ?" , nil).order("position") 
respond_to do |format| 
    format.json { render :json => @items } 
end 

@items將ItemSerializer自動序列化。

或者你可以選擇自定義序列

render json: @items, each_serializer: ItemWithAssociatedSerializer 
+1

重寫'as_json'就像我改變默認值,所以你可以通過傳遞'to_json'參數來回到以前的行爲。無論如何,使用序列化器更好(我用as_json,因爲這是官方推薦的方法),所以你是對的:) –

1

首先,我會建議使用寶石像ancestryawesome nested set。它將幫助您有效地管理您的Items樹結構(在一個SQL查詢中檢索整個層次結構,等等)。

那麼你可以做這樣的事情:

class Item 
    def as_json(options={}) 
    super({include: items}.merge options) 
    end 
end 

這意味着呼籲to_json上的項目會被默認包括孩子們的JSON;所以遞歸地我們走下整個層次結構。

如果您需要一種方法來限制嵌套的級別數,你可以這樣做:

class Item 
    def as_json(options={}) 
    return super({include: items}.merge options) unless options[:depth].present? 
    if options[:depth] > 0 
     super({include: items, depth: options[:depth] - 1}.merge options) 
    else 
     super 
    end 
    end 
end 
+0

這似乎不起作用(或者我需要先安裝寶石?)實際上是我的應用程序中唯一的這種情況,我不需要太多的選擇,但如果它們讓生活更輕鬆,我會查看那些寶石。謝謝! – networkprofile

+0

對不起,沒有測試過。什麼不行?第一個還是第二個解決方案? –

+0

哎呀,錯字。 '包括'=>''包括' –