mysqlruby-on-railsrubyactiverecordrails-bullet

acts_as_api and bullet N+1 queries


I am using acts_as_api to provide a JSON response for some models in my system. My API related code is (reduced to make the example easier):

# File app/modes/item.rb

# API
acts_as_api

api_accessible :v1_list do |template|
  template.add :id
  template.add :client_name
end

This API is working as expected. It is important to know that client_name is a method containing:

def client_name
    client.name
end

That is, the client name is not included in the item model but in the client model. Thus, this info is not contained in the items table.

Using Bullet gem I have noticed that a N+1 query is being performed in the clients table. For each item, a SQL query to the clients table is also performed.

I know that ActiveRecord has some utilities in the API that avoids N+1 queries, and I would like to know if there is a way to use that ActiveRecord feature together with acts_as_api gem.


Solution

  • The gem documentation shows this

    def index
      @users = User.all
    
      #Note that it’s wise to add a root param when rendering lists.
    
      respond_to do |format|
        format.xml  { render_for_api :name_only, :xml => @users, :root => :users  }
        format.json { render_for_api :name_only, :json => @users, :root => :users }
      end
    end
    

    So for your case you should simply eager load the client association

    def index
      @items = Item.includes(:client).all
    
      # Note that it’s wise to add a root param when rendering lists.
    
      respond_to do |format|
        format.xml  { render_for_api :name_only, :xml => @items, :root => :items  }
        format.json { render_for_api :name_only, :json => @items, :root => :items }
      end
    end