3

i have a table of data, which can have each other as parents or childs, its handled with the field parent_id (I am using the act_as_tree gem)

the first level items have 0 as parent_id

there could be an infinite number of children. I want to output as JSON. the final output shud be something like this

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

}

so far i all i have is this

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

clearly i haven't even come close to solving the problem. If someone could point me to the right direction i would really appreciate it. maybe there is a plugin that i don't know about that would help me solve this. thanks.

2 Answers 2

17

Your JSON example is invalid because there are multiple keys in the same object with the same name, but outputting a tree structure as JSON from an ActiveRecord object is definitely possible.

Try adding a method like this to your model class:

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

Now you can retrieve the entire tree as JSON using:

root = Coa.find(:first, :conditions => ["parent_id = ?", 0])
root.to_node.to_json
Sign up to request clarification or add additional context in comments.

1 Comment

thanks this did the trick. and i guess its cleaner to have the recursive function in the model.
4

The only thing I would add to Todd Yandell's answer is that it may be useful to not have separate keys for "attributes" and "children". In other words, while Yandell's method would return data like this:

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

You may wish for the data in the question, above, to be formatted like this:

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

That format is particularly useful with situations where client-side code expects tree-formatted JSON data and does not allow flexibility to define different keys for parent attributes and children (e.g., a NestedList component in Sencha Touch, etc.).

To accomplish this, building on Yandell's concept, I came up with the following:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.