Join the Stack Overflow Community
Stack Overflow is a community of 6.4 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I'm getting a bit stuck building a json object from a parent and child relationship. I have a Parent model with many Children.

I'm trying to create a JSON object as so:

{ parent_1.name: { parent_1.child.age, parent_1.child.height}, parent_1.name: { child_2.age, child_2.height}, parent_2.name: ...... }

This SO question has helped a lot but I can't figure it out completely.

I have tried this:

Parent.all.inject({}) { |hsh, p| hsh[p.name] = { p.name => p.children.inject({}) { |h,v| h[v] = {age: v.age, height: v.height}} }}

Which is really close (but horrible looking). However I only get one parent's children - I need all the parents with the children. I only need the height and age of the children. The output was like this (I have excluded the conversion to json):

{"BarryWhite"=>{:age=>"12", :height=>"45cm"}}

It should look something like this:

{"BarryWhite"=>{:age=>"12", :height=>"45cm"}, {:age => "34", :height => "108cm"}, "AndyMurray"=>{:age=>"14", :height=>"125cm"}}    

How can I get this to output the correctly formatted json.

share|improve this question
up vote 0 down vote accepted

First of all the JSON format you require is a bit incorrect.

I assume children should be an array of hashes, like:

{
  'BarryWhite' => [
    { :age => '12', :height => '45cm'  },
    { :age => '34', :height => '108cm' }
  ]
  'AndyMurray' => [
    { :age => '14', :height => '125cm' }
  ]
}

For this you don't need an inner #inject, as you don't need a hash, but an array.

Also you are using #inject a bit incorrectly with hashes. #inject builds up a hash by passing through the loop the last executed statement. Your last executed statement is an assignment which returns only the current value of a variable "p". You should return the whole "hsh" all the time.

Here is the working solution:

Parent.all.inject({}) do |hsh, p|
  hsh[p.name] = p.children.map { |c| {age: c.age, height: c.height} }
  hsh
end
share|improve this answer
    
Good point about the formatting. I'd forgotten to put that in.. Thanks, all sorted. S – simonmorley Jul 12 '13 at 15:20

Here's how I do it:

1) Each model has a to_json method

2) When rendering, render json: @items.collect(&:to_json)

I'm not sure why it doesn't automatically call to_json on child objects when array.to_json is called.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.