Alex Blakemore
Alex Blakemore

Reputation: 11896

How to avoid N+1 queries with will_paginate?

My app is slowed down by N+1 queries. I'm using the will_paginate gem with Rails 3.1 and Oracle 11.2.

Normally, the solution would be to use ActiveRecord#includes() to read in child records at the same time that I fetch the parent records, but every attempt I've made seems to either not work with will_paginate, or end up fetching the whole database into memory. I tried making a named scope, but it seems scopes are fetched immediately when called, not lazily.

class Parent < ActiveRecord::Base
  has_many :children, :dependent => :delete_all
end

class Child < ActiveRecord::Base
  belongs_to :parent
end

class ParentsController < ApplicationController
def index
  @parents = Parent.paginate page: params[:page], order: 'id', per_page: 32
end

Index.html.erb contains, among other things,

<%= page_entries_info @parents %>
<%= will_paginate @parents, :container => false %>
<% @parents.each do |parent| %>
<%= parent.call_to_method_that_uses_children_association_causing_N+1_query %>
<% end %>

If I can't afford to fetch the whole database into memory, and don't want to fetch a page of parents, followed by N child fetches, are there other options besides abandoning will_paginate?

Also, is there any substantial documentation for will_paginate? The info on github is pretty sparse. For example, what does the :container option to will_paginate method mean?

Upvotes: 3

Views: 1939

Answers (1)

Ransom Briggs
Ransom Briggs

Reputation: 3085

Parent.includes(:children).paginate(:page => params[:page], :per_page => 30)

From another question that is similar to yours

Upvotes: 7

Related Questions