ActiveRecord each_by_page
Step through and instantiate each member of the class and execute on it, but instantiate no more than per_page instances at any given time.
Safe for destructive actions or actions that modify the fields your :order or :conditions clauses operate on.
module ActiveRecord class Base def each_by_page per_page, options = {}, &block # By-id for model-modifying blocks # Build SQL to get ids of all matching records using the options provided by the user sql = construct_finder_sql(options.dup.merge({ :select => 'id' })) # Get the results as an array of tiny hashes { "id" => "1" } and flatten them out to just the ids all_ids = connection.select_all(sql).map { |h| h['id'] } at_a_time = 0..(per_page-1) # chop apart the all_ids array a segment at a time begin ids = all_ids.slice!(at_a_time) ids_cases = [] ids.each_with_index { |id, i| ids_cases << "WHEN #{id} THEN #{i}" } ids_cases = ids_cases.join(' ') # Do the deed on this page of results find(:all, options.merge( :conditions => [ 'id IN (?)', ids ], :order => "CASE id #{ids_cases} END" )).each &block end until all_ids.empty? end end end
link to blog entry