Jonathan Mui
Jonathan Mui

Reputation: 2511

One Rails route that responds to html and json with different queries

I have a simple index action in my controller that serves html and json formats.

def index
  @records = Model.all

  respond_to do |format|
    format.html
    format.json { render json: @records }
  end
end

I've recently redone the HTML view in AngularJS backed by the JSON endpoint. I've noticed from the logs that when loading the HTML for this action that the query is still being made for the HTML view even though I've setup AngularJS to fetch the records at the JSON endpoint on load.

I'm not sure of the best way to handle this. I'd like to be able to not query if I'm just responding to HTML. The obvious way would be to only run the query if the format is JSON, but I have a feeling that's not the best way.

Upvotes: 4

Views: 737

Answers (2)

cristian
cristian

Reputation: 8744

In Rails 3, calling all on a Model hits the database and retrieve the result. In Rails 3 Model.all.class = Array[Class] of activerecord objects.

If you want your query to be run only when you iterate over the collection in your view don't call .all directly on your Model class. You can do something like:

@records = Model.scoped

and in your view, when you need to display your collection:

<% @records.each do |record| %>
  <%= record.inspect %>
<% end %>

In Rails 4, all returns an ActiveRecord_Relation object and not hits the database until you iterate over your collection.

More info at: http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-all

Upvotes: 1

nathanvda
nathanvda

Reputation: 50057

You can solve that simply by doing

def index
  respond_to do |format|
    format.html
    format.json { 
      @records = Model.all
      render json: @records 
    }
  end
end

Upvotes: 1

Related Questions