views:

19

answers:

3

Hi everyone,

In my Item controller, I wish to add a transient (i.e. non-persistent) attribute to my model object before rendering it as JSON.

def show

    @item = Item.find(params[:id])
    @item.comment = "some comment"

    render :json => @item 
end

My Item class looks like this:

class Item < ActiveRecord::Base

    attr_accessor :comment
    @comment

end

My problem is that the comment instance variable is not being rendered in the JSON. Everything that is persistent appears in the JSON output. Do I need to override the to_json method in order to make this work? Or is there an easier way to ensure that the comment is rendered in the JSON output?

Thanks for your help.

-------------- Update

This is the solution that has evolved out of Chubas suggestion. Overriding the to_json method on Item:

def to_json(options = {})

    options[:methods] = :comment;

    super(options)

end

Would love to know if this concurs with your thoughts, Chubas.

A: 

I would recommend you construct the object to be converted to json yourself. This both will remove the problem you're having with the comment and will prevent you from accidentally exposing information you don't want to provide.

Something like:

render :json => {
  :item => {
    :name => 'Some Item',
    ...
    :comment => 'Some Comment
  }
}
Jamie Wong
+1  A: 

If you want more control over what to render, rather than creating the json object in the controller (bad design), override the method as_json in the model, calling super and using the methods option to include :comment. You can see the default behavior here

Chubas
Hi there, thanks for your reply.. I would like to implement this approach but I've found myself fumbling around trying to figure out what the overridden as_json method should look like. Any chance you could describe this solution a little further? Thanks again.
David Sisters
A: 

You should be able to do this by using :include

@item.to_json(:include => :comments)

or :methods

@item.to_json(:methods => :comments)
Mr. Matt