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 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 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 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]
-
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 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...)
-
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.
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
Tags
Referenced by
- 85 failures linked to association extensions Showing app/views/shared/_printlist.rhtml where line #18...
- 250 NoMethodError on first page (Multiple associations) Showing app/views//tracks.html.erb where line #18 raised:
- 250 NoMethodError on first page (Multiple associations) You have a nil object when you didn't expect it! The erro...