views:

7252

answers:

4

I'm looking to render an index of all articles along with a full article via json in my rails app, but I'm having a little trouble figuring out how to do it.

Here is my controller now:

if params[:id]
    @article = Article.find(params[:id])
else
    @article = Article.published.not_draft.by_recent.first
end

respond_to do |format|

format.js { render :json => @article.to_json(
:except => [ :created_at, :updated_at, :draft, :id, :publish ], 
:include => {
 :comments => {
  :only => [:body]
 }
}),
:callback => params[:callback]}
end

What I'd like to do in the response is add an index of all articles, like so:

@index = Article.find(:all, :select => 'id, title')

The only way I've been able to do it, is put both the index and article into a hash or array and then put that to json.

@response = { :item => @article, :index => @index }

Full code with both:

@index = Article.find(:all, :select => 'id, title')

if params[:id]
    @article = Article.find(params[:id])
else
    @article = Article.published.not_draft.by_recent.first
end

@response = { :item => @article, :index => @index }

respond_to do |format|

format.js { render :json => @response.to_json(), :callback => params[:callback]}

end

This would be fine, except now I cannot specify :include or :except and get it to render properly.

I'm really stuck here. Any help would be appreciated. Thanks.

A: 

You should be able to nest the :include, :except, etc. like so:

:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}...

If that doesn't work, make it an object (e.g. an OpenStruct) instead of a hash.

-- Markus

MarkusQ
A: 

Just to be clear the code above works with the :include and :except. And by works I mean it doesn't throw an error. The problem is it includes comments for every article in the index. I'm only looking to include comments for the :item and not any of the articles listed in the index.

I couldn't get nesting to work as a hash or an OpenStruct object.

Nesting on :include throws an error, nesting on :except doesn't throw an error, but nothing is filtered out, :created_at, etc. still show up.

...

@response = { :item => @article, :index => @index }

format.js { render :json => @response.to_json(
:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}, 
:include => { :item => {
        :comments => {
                :only => [:body]
        }
}}),
:callback => params[:callback]}
end
A: 

to_json has a :method option that includes the result of any method you name, you could define a method on that model that returns the additional data you want in your JSON.

DavidNorth
+1  A: 

You hint at the solution in your question. You most likely want to build up a hash to render to JSON. The preferred way of doing this now is by providing an implementation for the as_json method. as_json provides a formal means of customizing to_json output by building up a hash containing the data you wish to encode.

A more thorough treatment of how as_json and to_json interact can be found on Jonathan Julian's weblog.

nirvdrum