#18 ✓resolved
Wade Winningham

will_paginate ignores the :include with has_many

Reported by Wade Winningham | June 27th, 2007 @ 11:50 AM

I setup a paginate for a has_many relationship that has an :include piece to it. Some of the conditions rely on the included tables and will_paginate was not using them.

EXAMPLE

class Producer < ActiveRecord::Base
  has_many :active_cases, :class_name => "Case", :include => [:employer => :carrier], :conditions => "employers.date_cancelled IS NULL"
end

class ProducersController < ApplicationController
  def show
    @producer = Producer.find(params[:id])
    @active_cases, @page = @producer.active_cases.paginate(
        :page => params[:page],
        :order => "employers.name",
        :per_page => 10
      )
  end
end

The above code gives me an error on the "employers.name" column.

TEMPORARY SOLUTION

Add the appropriate :include along with the call to paginate. This makes things work, but not very DRY.

Comments and changes to this ticket

  • Mislav

    Mislav June 27th, 2007 @ 11:50 AM

    • State changed from “new” to “open”
    • Assigned user changed from “Chris Wanstrath” to “Mislav”

    Hmm I need to investigate is pagination really possible with eager loading because it relies on SQL limit and offset.

    Thanks for the report. BTW, your example uses the old-style call to "paginate". In the new version of will_paginate only one argument is returned: the collection. Current page is saved internally.

  • Jonathan del Strother
  • Jonathan del Strother

    Jonathan del Strother June 27th, 2007 @ 11:50 AM

    FWIW, we've had good results with something like this :

    class ActiveRecord::Associations::AssociationCollection
      include WillPaginate::Finder::ClassMethods
      alias_method_chain :method_missing, :paginate
    end
    

    The only problem with mixing WillPaginate into rails' associations is that you have to be really careful with missing methods. For instance, 'returning' (used at the end of method_missing_with_paginate) is undefined from association_proxy.rb:8. This then prompts a load_target, *loading your entire collection*, before 'returning' is forwarded on to the loaded collection.

    After replacing the returning block with the non-K-combinator equivalent, it all seems to work great.

  • Chris Wanstrath

    Chris Wanstrath June 27th, 2007 @ 11:50 AM

    • State changed from “open” to “resolved”

    (from [278]) Will Paginate: make the finders apply to association proxies, also. This fixes the issues you could be having when doing something like user.projects.paginate() with conditions or eager loading. [Jon] [#18 state:resolved]

    http://require.errtheblog.com/pl...

  • Mislav

    Mislav June 27th, 2007 @ 11:50 AM

    Thanks Jon. However, I didn't remove the K combinator yet. Can you explain why prompting the load target for "returning" makes the entire collection load?

    Any tips on how can I inspect AssociationProxy (and subclasses) instances to see exactly what gets loaded and when? (Think of this as a generic Rails question.)

  • Jonathan del Strother

    Jonathan del Strother June 27th, 2007 @ 11:50 AM

    It's kinda a total pain, actually - I spent the entire morning in ruby-debug, trying to figure out why Rails was trying to load my entire table rather than just a single page.

    First, the association proxy has had 90% of the usual methods removed (see association_proxy.rb:8). This includes 'returning'. So, calling returning will end up at method_missing on the proxy (association_proxy.rb:127), which calls load_target, which loads your entire collection (scoped by whatever has_many parameters you've defined), before forwarding 'returning' onto the loaded collection. The real collection still has the 'returning' method from misc:rb, and so it executes as expected.

    The transparency of the proxy made this a little difficult to track down. For instance, calling respond_to?(:returning) returns true, since respond_to? is no longer defined on the proxy and it forwards on to the load target. It took me a while to figure out why 'debugger' was prompting method_missing - again, it's forwarding through to the target.

    As for tracking what gets loaded when... printing sql to stdout when you're in the console is handy (http://weblog.jamisbuck.org/2007...), as is the query_trace plugin (https://terralien.devguard.com/s...)

  • Mislav

    Mislav June 27th, 2007 @ 11:50 AM

    So what do you think of [280] then?

  • Jonathan del Strother

    Jonathan del Strother June 27th, 2007 @ 11:50 AM

    Ah, hadn't thought of just calling Object.returning directly. Seems to work nicely.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

Everyone's favorite Ruby library for pagination of practically anything!

People watching this ticket

Referenced by

Pages