Paginate custom finders
Reported by Andreas Neuhaus | July 26th, 2007 @ 07:31 PM
I'm having problems using will_paginate with a custom finder method in my models:
class User < AR::Base
def find_all_special (options = {})
with_scope(:find => {:conditions => "...", :order => "..." }) do
find(:all, options)
end
end
end
Retrieving records by using @users=User.paginate_special(...) does work, because using paginate_xyz calls find_all_xyz and adds offset/limit options to retrieve the records. However the paginate method does not retrieve the correct record count. It uses the count method but isn't able to apply the scope that could be applied in a custom finder method. Therefore the will_paginate helper displays more pages than actually exist.
Because I want to keep the search conditions within my model classes, I solved this problem by adding a count_special method which returns the number of records by using "count" within the proper scope. However now I have to specify :total_entries => User.count_special whenever using paginate_special; which isn't very DRY (and I tend to forget to add this option sometimes)
It would be nice if will_paginate would automatically use a custom counter method if such one exists (like automatically using count_special if paginate_special is used).
Or does somebody else maybe know a better way to paginate cutstom finder methods in a DRY way?
Comments and changes to this ticket
-
Chris Wanstrath July 26th, 2007 @ 07:31 PM
- State changed from new to open
- Assigned user changed from Chris Wanstrath to Mislav
-
Andreas Neuhaus July 26th, 2007 @ 07:31 PM
I wrote up a more detailed description of this problem in a posting in my Blog
-
Mislav July 26th, 2007 @ 07:31 PM
- State changed from open to invalid
So, you would like this:
class User < AR::Base def self.find_all_special(options = {}) with_scope(:find => { :conditions => "...", :order => "..." }) do find(:all, options) end end def self.count_special(options = {}) with_scope(:find => { :conditions => "...", :order => "..." }) do count(options) end end end User.paginate_special(:page => 1)
Right?
But don't you see that you didn't manage to stay DRY anyway? It is because you're using with_scope totally wrong. Isn't this much better?
class User < AR::Base def self.paginate_special(options) with_scope(:find => { :conditions => "...", :order => "..." }) do paginate(options) end end end User.paginate_special(:page => 1)
Or even this
class Developer < User def self.with_poor_ones(&block) with_scope :find => { :conditions => ['salary <= ?', 80000], :order => 'salary' } do yield end end end Developer.with_poor_ones do Developer.paginate :page => 1 end
But this last example may be frowned upon by Rails purists. Better stick with the middle example.
-
Andreas Neuhaus July 26th, 2007 @ 07:31 PM
Thanks, Mislav. Indeed using a custom paginate method would solve the problem - however, only if you need just the paginate method. If you also need the non-paginated custom finder somewhere, you'd become non-DRY again (more on that in my reply to your comment post in my blog).
Another idea came into my mind: will_paginate is easy to use, because it's unobstrusive. You write models like before and get pagination on top by installing will_paginate. It would be nice if that could also be possible with custom finders. It almost works already - except that the wrong count of total records is retrieved. To get the right count, all that would be required, is to let the custom finder build the SQL conditions like before and use it with count ('select count(*)') instead of find ('select *'). I'm not sure how AR works and if this is even possible without chaning AR itself, but that would be a great will_paginate feature.
-
Mislav July 26th, 2007 @ 07:31 PM
At first I thought it was a good feature, yes. But then I though about
how this custom counters would be implemented, and I realized users
would have to duplicate logic in finders and corresponding counters.
So, will_paginate would support bad coding practice then.
-
Adam Cohen August 23rd, 2007 @ 11:33 PM
I echo your concerns Zargony, I'd love to see support for custom complex finders as well. Is this a possibility in the future Mislav?
-
Mislav August 24th, 2007 @ 12:14 AM
Will Paginate now supports the scope_out plugin. Continue the discussion on the blog...
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
- 146 how to get the right count when using will_paginate and attachment_fu? see my comments on #66