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.