lib/will_paginate/finder.rb in will_paginate-2.1.0 vs lib/will_paginate/finder.rb in will_paginate-2.2.0

- old
+ new

@@ -1,10 +1,10 @@ require 'will_paginate/core_ext' module WillPaginate # A mixin for ActiveRecord::Base. Provides +per_page+ class method - # and makes +paginate+ finders possible with some method_missing magic. + # and hooks things up to provide paginating finders. # # Find out more in WillPaginate::Finder::ClassMethods # module Finder def self.included(base) @@ -16,13 +16,13 @@ end end # = Paginating finders for ActiveRecord models # - # WillPaginate adds +paginate+ and +per_page+ methods to ActiveRecord::Base - # class methods and associations. It also hooks into +method_missing+ to - # intercept pagination calls to dynamic finders such as + # WillPaginate adds +paginate+, +per_page+ and other methods to + # ActiveRecord::Base class methods and associations. It also hooks into + # +method_missing+ to intercept pagination calls to dynamic finders such as # +paginate_by_user_id+ and translate them to ordinary finders # (+find_all_by_user_id+ in this case). # # In short, paginating finders are equivalent to ActiveRecord finders; the # only difference is that we start with "paginate" instead of "find" and @@ -82,9 +82,34 @@ pager.replace send(finder, *args, &block) # magic counting for user convenience: pager.total_entries = wp_count(count_options, args, finder) unless pager.total_entries end + end + + # Iterates through all records by loading one page at a time. This is useful + # for migrations or any other use case where you don't want to load all the + # records in memory at once. + # + # It uses +paginate+ internally; therefore it accepts all of its options. + # You can specify a starting page with <tt>:page</tt> (default is 1). Default + # <tt>:order</tt> is <tt>"id"</tt>, override if necessary. + # + # See http://weblog.jamisbuck.org/2007/4/6/faking-cursors-in-activerecord where + # Jamis Buck describes this and also uses a more efficient way for MySQL. + def paginated_each(options = {}, &block) + options = { :order => 'id', :page => 1 }.merge options + options[:page] = options[:page].to_i + options[:total_entries] = 0 # skip the individual count queries + total = 0 + + begin + collection = paginate(options) + total += collection.each(&block).size + options[:page] += 1 + end until collection.size < collection.per_page + + total end # Wraps +find_by_sql+ by simply adding LIMIT and OFFSET to your SQL string # based on the params otherwise used by paginating finds: +page+ and # +per_page+.