Ruby on Rails - Bullet/N+1

performance, rails-bullet, ruby-on-rails

Solution

Just to be more clear, let me make the details more visible:

class User < ActiveRecord::Base
  has_many :submissions
end

class Submission < ActiveRecord::Base
  belongs_to :category
  belongs_to :user
  has_many   :submission_details
end

class SubmissionDetail < ActiveRecord::Base
  belongs_to :submission
end

class Category < ActiveRecord::Base
  belongs_to :award
  has_many   :submissions
end

class Award < ActiveRecord::Base
  has_many :categories
  has_many :submissions, through: :categories
end

If I understand correctly, for your current_user, you are listing his submissions. For each submission you want to list submission_details and the category it belongs. For every category you list the award too.

<% current_user.submissions.order('created_at DESC').in_groups_of(3, false) do |group| %>
  <div class="row">
    <% group.each do |submission| %>
      ...
      <div><%= submission.category %></div>
      <div><%= submission.category.award %></div>
      <%= submission.submissions_details.each do |submission_detail| %>
        ...
      <% end %>
    <% end %>
  </div>
<% end %> 

You can remove N+1 problem by using `includes` in the following manner:

current_user.submissions.includes(:submission_details, :category => :award)

For more details about `includes` please refer to:

- Rails guides eager-loading-associations

- Rails guides eager-loading-multiple-associations

- Rails api - includes

associations

Problem

On Rails 4. I recently installed the bullet gem for my development environment to clear up my app's N+1 queries. Relevant models: Submissions: Belongs to Categories and Users. Has many SubmissionDetails. Users: Has many Submissions Categories: Has many Submissions. Belongs to Awards. Awards: Has many Categories (and Submissions through Categories) SubmissionDetails: Belongs to Submissions In my submission's index page, I have an `each do` statement to display each submission made by the current user. ``` <% current_user.submissions.order('created_at DESC').in_groups_of(3, false) do |group| %> <div class="row"> <% group.each do |submission| %> ``` After that, I list information about the submission, including its associated category, award, and submission details information. Bullet is saying I'm having N+1 issues with this statement: ``` N+1 Query detected Submission => [:category] Add to your finder: :include => [:category] N+1 Query detected Submission => [:user] Add to your finder: :include => [:user] N+1 Query detected Submission => [:submission_details] Add to your finder: :include => [:submission_details] ``` Every time I try to add `.includes` with all three of those models, it only picks the first one I list (this is not surprising). I figure I need to go a different route when multiple models are involved--perhaps a join statement? (When I make :category the first item, it adds this notice): ``` N+1 Query detected Category => [:award] Add to your finder: :include => [:award] ``` (So I also need to include as part of the statement a way to make Award fit in there as well, which, again, has many Submissions through Categories). So assuming I can't do one `.includes` for three different models, is there another way to go about this? Thanks.

Original source