我有一个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
答案 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)
首先,我建议使用像ancestry或awesome 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