Module: ActiveRecord::Batches

Defined in:
lib/in_batches/active_record/batches.rb,
lib/in_batches/active_record/relation/batch_enumerator.rb

Defined Under Namespace

Classes: BatchEnumerator

Instance Method Summary collapse

Instance Method Details

#in_batches(of: 1000, begin_at: nil, end_at: nil, load: false) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/in_batches/active_record/batches.rb', line 5

def in_batches(of: 1000, begin_at: nil, end_at: nil, load: false)
  relation = self
  unless block_given?
    return BatchEnumerator.new(of: of, begin_at: begin_at, end_at: end_at, relation: self)
  end

  if logger && (arel.orders.present? || arel.taken.present?)
    logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size")
  end

  relation = relation.reorder(batch_order).limit(of)
  relation = apply_limits(relation, begin_at, end_at)
  batch_relation = relation

  loop do
    if load
      records = batch_relation.to_a
      ids = batch_relation.pluck(primary_key)
      relation_yielded = self.where(primary_key => ids).reorder(batch_order)
      relation_yielded.load_records(records)
    else
      ids = batch_relation.pluck(primary_key)
      relation_yielded = self.where(primary_key => ids).reorder(batch_order)
    end

    break if ids.empty?

    primary_key_offset = ids.last
    raise ArgumentError.new("Primary key not included in the custom select clause") unless primary_key_offset

    yield relation_yielded

    break if ids.length < of
    batch_relation = relation.where(table[primary_key].gt(primary_key_offset))
  end
end