I’ve been enjoying using has_finder by Nick at Pivotal Labs and recently added pagination to the application I am providing volunteer time to for the San Francisco Bike Kitchen.
I like the semantics of paginating_find over will_paginate but am not married to that choice if anyone wants to try to convince me otherwise.
In any case, I wanted to paginate the finders created by has_finder. I wrote a simple ActiveRecord mixin that provides a class method ‘acts_as_paginated and is used in your model like:
class Visit 10 has_finder :for_person, lambda { |person| { :conditions => { :person_id => person}, :order => 'datetime DESC' } } has_finder :in_date_range, lambda { |from,to| { :conditions => [ "visits.datetime >= ? and visits.datetime <= ?", from, to ] } } end
Client code looks like:
from, to = Date.new(2008,2,1), Date.new(2008,2,3) visits = Visit.for_person(@person).in_date_range(from, to).paginate(:page => 3)
The mixin looks like:
# Provides Model.paginate(options={}) to allow # the paginating_find plugin to be used with the has_finder plugin. # # Usage: # acts_as_paginated # acts_as_paginated :page => 2, size => 10 # # Install: # Save this file as lib/acts_as_paginated.rb and require 'acts_as_paginated' # in environment.rb. # module HasFinder module PaginatingFind #:nodoc: def self.included(mod) mod.extend(ClassMethods) end module ClassMethods def acts_as_paginated(options={ :page => 1, :size => 20}) cattr_accessor :paginate_defaults self.paginate_defaults = options self.class_eval do extend HasFinder::PaginatingFind::SingletonMethods end end end module SingletonMethods def paginate(args={}) options = self.paginate_defaults.clone options[:page] = args[:page].to_i if args[:page] options[:size] = args[:size].to_i if args[:size] find(:all, :page => { :size => options[:size], :current => options[:page], :first => 1 }) end end end end ActiveRecord::Base.send(:include, HasFinder::PaginatingFind)
It also works to paginate associations:
@person.visits.paginate(:size => 4)