1

I have an Item class that also contains many items (using has_many). What I want to do is read all items that have no parent (the top level) and all their subitems. So basically I need my entire Item table nested correctly, into json.

This is the code I'm using right now, but this only returns the top level items and their items, it doesn't go any lower than that. (So I'm left with only two levels)

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

2 回答 2

1

不建议覆盖 as_json 或 to_json

原因是您将需要其他地方的原始数据,并且您可能需要其他格式的数据。Manipulateas_json最终会改变数据,你没有办法扩展。

使用装饰器是要走的路。一个不错的选择 gem 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
于 2013-10-26T14:02:12.203 回答
0

首先,我建议使用像ancestryawesome nested set这样的 gem 。它将帮助您有效地管理您的项目树结构(在一个 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
于 2013-10-26T13:45:41.913 回答