Rails,创建树状结构。 JSON输出

时间:2011-04-08 05:23:06

标签: ruby-on-rails ruby json ruby-on-rails-3

我有一个数据表,可以互为父母或孩子,用字段parent_id处理(我使用的是act_as_tree宝石)

第一级项目的0为parent_id

可能会有无数的孩子。我想输出为JSON。 最后的输出就像是这样的

{
   "feild1": "dd",
   "filed2": "ee",
   "child" : {
       "feild1": "dd",
        "filed2": "ee",
        } 
   "child" : {
        "feild1": "dd",
        "filed2": "ee",
                 "child" : {
                      "feild1": "dd",
                      "filed2": "ee",
                  } 
        } 

}

到目前为止,我所拥有的只是这个

def coa_tree
   @roots = Coa.find(:all, :conditions => ['parent_id = ?', 0])
   @response = @roots

   @roots.each do |root|
     logger.debug "roots each"
      output = root
      root.children.each do |child|
           output = {:child => output, :child => child}

      end

   end
   respond_with(@response)
end
显然,我甚至没有接近解决问题。如果有人能指出我正确的方向,我会非常感激。也许有一个我不知道的插件可以帮助我解决这个问题。 感谢。

2 个答案:

答案 0 :(得分:13)

您的JSON示例无效,因为同一对象中有多个具有相同名称的键,但是从ActiveRecord对象输出树结构绝对是可能的。

尝试将类似这样的方法添加到模型类中:

class Coa < ActiveRecord::Base
  def to_node
    { "attributes" => self.attributes,
      "children"   => self.children.map { |c| c.to_node }
    }
  end
end

现在,您可以使用以下方法将整个树检索为JSON:

root = Coa.find(:first, :conditions => ["parent_id = ?", 0])
root.to_node.to_json

答案 1 :(得分:4)

我唯一要添加到Todd Yandell的答案是,没有单独的“属性”和“孩子”键可能会有用。换句话说,虽然Yandell的方法会返回这样的数据:

{
   "attributes" : {
        "field1": "dd",
        "field2": "ee",
   "children" : [{
        "field1": "dd",
        "field2": "ee",
    }, {
        "field1": "dd",
        "field2": "ee",
    }, {
        "field1": "dd",
        "field2": "ee",
    }]
}

您可能希望上面问题中的数据格式如下:

{
   "field1": "dd",
   "field2": "ee",
   "children" : [{
        "field1": "dd",
        "field2": "ee",
    }, {
        "field1": "dd",
        "field2": "ee",
    }, {
        "field1": "dd",
        "field2": "ee",
    }]
}

在客户端代码需要树格式的JSON数据并且不允许灵活地为父属性和子节点定义不同的键(例如,Sencha Touch中的NestedList组件等)的情况下,该格式特别有用。 / p>

为了实现这一目标,在Yandell的概念基础上,我想出了以下内容:

def to_node
  self.attributes.merge({:children => self.children.map { |c| c.to_node }})
end