Rails to_json与所有关系

时间:2013-10-26 12:48:03

标签: ruby-on-rails ruby json activerecord has-many

我有一个Item类,它也包含很多项(使用has_many)。我想要做的是阅读所有没有父级(顶级)及其所有子项的项目。所以基本上我需要将整个Item表正确嵌套到json中。

这是我现在使用的代码,但这只返回顶级项目及其项目,它不会低于此值。 (所以我只留下两个级别)

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

2 个答案:

答案 0 :(得分:1)

不建议覆盖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 :(得分:0)

首先,我建议使用像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