1

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.

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

1 Comment

Good point about the formatting. I'd forgotten to put that in.. Thanks, all sorted. S
0

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.

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.