Method: EachBatch::BatchEnumerator#each

Defined in:
lib/each_batch/batch_enumerator.rb

#eachObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/each_batch/batch_enumerator.rb', line 41

def each
  return self unless block_given?

  batch_relation = relation.reorder(keys.product([order]).to_h).limit(batch_size)
  batch_relation.skip_query_cache! # Retaining the results in the query cache would undermine the point of batching

  yielded_relation = batch_relation
  op = order.to_s.casecmp('desc').zero? ? :lt : :gt
  pk = relation.primary_key.to_sym

  loop do
    # consistent with rails load behavior.
    if @load
      records = yielded_relation.records
      yielded_relation = relation.where(pk => records.map(&pk))
      yielded_relation.send(:load_records, records)
    end

    yield yielded_relation

    offsets =
      if @load || yielded_relation.loaded?
        break if yielded_relation.length < batch_size

        yielded_relation.last.attributes_before_type_cast&.values_at(*keys)
      else
        # we need an additional query to fetch the last key set
        offsets = yielded_relation.offset(batch_size - 1).limit(1).pluck(*keys).first

        break if offsets.nil?

        Array.wrap(offsets)
      end

    yielded_relation = batch_relation.where_row(*keys).public_send(op, *offsets)
  end
end