module ActiveRecord::FindInBatchesWithOrder
Constants
- VERSION
Public Instance Methods
find_each_with_order(options = {}) { |record| ... }
click to toggle source
note that in strict mode we might itereate perpetually if the overlap in values is too high in relation to the batch size
# File lib/ar-find-in-batches-with-order.rb, line 40 def find_each_with_order(options = {}) last_record = nil find_in_batches_with_order(options) do |records| records.each do |record| # we need to find the last record of the previous batch next if last_record and (record != last_record) if last_record last_record = nil next end yield record end last_record = records.last end end
find_in_batches_with_order(options = {}) { |records| ... }
click to toggle source
# File lib/ar-find-in-batches-with-order.rb, line 5 def find_in_batches_with_order(options = {}) relation = self # we have to be explicit about the options to ensure proper ordering and retrieval direction = options.delete(:direction) || (arel.orders.first.try(:ascending?) ? :asc : nil) || (arel.orders.first.try(:descending?) ? :desc : nil) || :desc start = options.delete(:start) batch_size = options.delete(:batch_size) || 1000 # try to deduct the property_key, but safer to specificy directly property_key = options.delete(:property_key) || arel.orders.first.try(:value).try(:name) || arel.orders.first.try(:split,' ').try(:first) sanitized_key = ActiveRecord::Base.connection.quote_column_name(property_key) relation = relation.limit(batch_size) # in strictmode, we return records with same values as the last record of the last batch strict_mode = options.delete(:strict_mode) || true records = start ? (direction == :desc ? relation.where("#{sanitized_key} <= ?", start).to_a : relation.where("#{sanitized_key} >= ?", start).to_a) : relation.to_a while records.any? records_size = records.size yield records break if records_size < batch_size start = records.last.try(property_key) records = strict_mode ? (direction == :desc ? relation.where("#{sanitized_key} <= ?", start).to_a : relation.where("#{sanitized_key} >= ?", start).to_a) : (direction == :desc ? relation.where("#{sanitized_key} < ?", start).to_a : relation.where("#{sanitized_key} > ?", start).to_a) end end