method

batch_on_unloaded_relation

Importance_0
v8.1.1 - Show latest stable - 0 notes - Class: ActiveRecord::Batches
batch_on_unloaded_relation(relation:, start:, finish:, load:, cursor:, order:, use_ranges:, remaining:, batch_limit:) private

No documentation

This method has no description. You can help the Ruby on Rails community by adding new notes.

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
Register or log in to add new notes.