method
batch_on_unloaded_relation
v8.1.1 -
Show latest stable
-
0 notes -
Class: ActiveRecord::Batches
- 1.0.0
- 1.1.6
- 1.2.6
- 2.0.3
- 2.1.0
- 2.2.1
- 2.3.8
- 3.0.0
- 3.0.9
- 3.1.0
- 3.2.1
- 3.2.8
- 3.2.13
- 4.0.2
- 4.1.8
- 4.2.1
- 4.2.7
- 4.2.9
- 5.0.0.1
- 5.1.7
- 5.2.3
- 6.0.0
- 6.1.3.1
- 6.1.7.7
- 7.0.0
- 7.1.3.2 (0)
- 7.1.3.4 (0)
- 7.2.3 (0)
- 8.0.0 (0)
- 8.1.1 (0)
- What's this?
batch_on_unloaded_relation(relation:, start:, finish:, load:, cursor:, order:, use_ranges:, remaining:, batch_limit:)
private
Hide source
# File activerecord/lib/active_record/relation/batches.rb, line 426 def batch_on_unloaded_relation(relation,, start,, finish,, load,, cursor,, order,, use_ranges,, remaining,, batch_limit)) batch_orders = build_batch_orders(cursor, order) relation = relation.reorder(batch_orders.to_h).limit(batch_limit) relation = apply_limits(relation, cursor, start, finish, batch_orders) relation.skip_query_cache! # Retaining the results in the query cache would undermine the point of batching batch_relation = relation empty_scope = to_sql == model.unscoped.all.to_sql loop do if load records = batch_relation.records values = records.pluck(*cursor) values_size = values.size values_last = values.last yielded_relation = rewhere(cursor => values) yielded_relation.load_records(records) elsif (empty_scope && use_ranges != false) || use_ranges # Efficiently peak at the last value for the next batch using offset and limit. values_size = batch_limit values_last = batch_relation.offset(batch_limit - 1).pick(*cursor) # If the last value is not found using offset, there is at most one more batch of size < batch_limit. # Retry by getting the whole list of remaining values so that we have the exact size and last value. unless values_last values = batch_relation.pluck(*cursor) values_size = values.size values_last = values.last end # Finally, build the yielded relation if at least one value found. if values_last yielded_relation = apply_finish_limit(batch_relation, cursor, values_last, batch_orders) yielded_relation = yielded_relation.except(:limit, :order) yielded_relation.skip_query_cache!(false) end else values = batch_relation.pluck(*cursor) values_size = values.size values_last = values.last yielded_relation = rewhere(cursor => values) end break if values_size == 0 if [values_last].flatten.any?(nil) raise ArgumentError, "Not all of the batch cursor columns were included in the custom select clause " "or some columns contain nil." end yield yielded_relation break if values_size < batch_limit if limit_value remaining -= values_size if remaining == 0 # Saves a useless iteration when the limit is a multiple of the # batch size. break elsif remaining < batch_limit relation = relation.limit(remaining) end end batch_orders_copy = batch_orders.dup _last_column, last_order = batch_orders_copy.pop operators = batch_orders_copy.map do |_column, order| order == :desc ? :lteq : :gteq end operators << (last_order == :desc ? :lt : :gt) cursor_value = values_last batch_relation = batch_condition(relation, cursor, cursor_value, operators) end nil end

