5

I have the following controller:

@moulding = Moulding.find( params[:id].split(","), :select => 'id, cost, width' )
@mount = MaterialCost.find(1).cost_per_square_mm
@glass = MaterialCost.find(2).cost_per_square_mm
@backing_board = MaterialCost.find(3).cost_per_square_mm
@vat = AppOption.find( 1, :select => 'value' )
@wastage = AppOption.find( 2, :select => 'value' )
@markup = AppOption.find( 3, :select => 'value' )

respond_to do |format|
  format.json { render :json => { :moulding => @moulding, :mount => @mount, :glass => @glass, :backing_board => @backing_board, :vat => @vat, :wastage => @wastage, :markup => @markup } }
end

The JSON output is as follows:

{"moulding":[{"moulding":{"cost":"3.1","id":2,"width":45}},{"moulding":{"cost":"1.5","id":4,"width":30}},{"moulding":{"cost":"2.1","id":6,"width":50}}],"mount":"0.00000246494303242769","glass":"0.0000032426589803639","backing_board":"0.00000135110790848496","vat":{"app_option":{"value":"17.5"}},"wastage":{"app_option":{"value":"20"}},"markup":{"app_option":{"value":"3"}}}

I would like the JSON to be in the following format:

{"mouldings":[{"2":{"cost":"3.1","width":45}},{"4":{"cost":"1.5","width":30}},{"6":{"cost":"2.1","width":50}}],"mount":"0.00000246494303242769","glass":"0.0000032426589803639","backing_board":"0.00000135110790848496","vat":{"app_option":{"value":"17.5"}},"wastage":{"app_option":{"value":"20"}},"markup":{"app_option":{"value":"3"}}}

The reason I want to do this is so I can extract the data for a particular moulding by id from the JSON string. How can I reformat the rendered JSON?

1 Answer 1

3

In my original answer, I made the mistaken assumption that @moulding was a single object, when in fact it was a set of objects. The answer would have worked in that case. To do what you want for the mouldings, you will have to repack the set of objects. That would look like this:

@moulding.collect! do |moulding|
    { moulding.id => {:cost=>moulding.cost, :width=>moulding.width}}
end

respond_to do |format|
    format.json { render :json => { :moulding => @moulding, :mount => @mount, :glass => @glass, :backing_board => @backing_board, :vat => @vat, :wastage => @wastage, :markup => @markup } }
end 

The collect method will iterate over all the items in the set of mouldings you have, and put the return value into a new array for you. The collect! method does this in place (modifies the array you are working on). If you want to assign it to a new variable, that's fine.

Essentially, I turned the moulding objects into sets of hashes. The final output would look like like you wanted.


old answer:

It appears that what you want to do is to change the :moulding key in your code to the item id. Example:

format.json { render :json => { @moulding.id => @moulding, :mount => @mount, :glass => @glass, :backing_board => @backing_board, :vat => @vat, :wastage => @wastage, :markup => @markup } }

I'm not exactly sure how to suppress the ID off the top of my head, but repeating the ID shouldn't hurt anything.

NOTE: The moulding key name is using the @ prefix instead of the symbol that was there before. It is a very subtle and easily overlooked detail.

Sign up to request clarification or add additional context in comments.

4 Comments

@Berin Loritsch - Using @moulding.id gives an error undefined method id'`.
Are you sure you have @ instead of :? I would expect :moulding.id to throw that error.
@Berin Loritsch - Yes I am using @moulding.id => @moulding
@freshest, My appologies. I made a faulty assumption about the content of the @moulding variable. I've updated the answer to reflect my better understanding of what the value was, as well as keep the original answer for context with the comments.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.