ActiveRecord::Batches module provides methods like find_each
, find_in_batches
,
and in_batches
to process records in batches, reducing memory consumption.
By default, records are processed in ascending order by primary key(ID).
# default asc order
User.find_each do |user|
puts user.id
end
User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1000]]
1
2
3
Before
Before Rails 7.1, ActiveRecord::Batches
methods - like find_each
, find_in_batches
,
and in_batches
supported ORDER BY
the primary key (ID) in either ascending or descending order.
class User < ApplicationRecord
self.primary_key = [:first_name, :last_name]
end
# Before Rails 7.1, trying to pass an array [:desc, :asc] to the order clause raised ArgumentError
User.find_each(order: [:asc, :desc]) do |user|
puts "#{user.first_name} #{user.last_name}"
end
:order must be :asc or :desc, got [:asc, :desc] (ArgumentError)
We could only specify a single sorting direction (:asc or :desc) as it only supported ORDER BY
on single primary column.
This restriction made it impossible to sort by multiple columns, such as having one column in ascending order while sorting another column in descending order, as ActiveRecord::Batches
did not support multi-column ordering.
After
Rails 7.1 adds support for batching using composite primary keys and multiple column ordering.
It allows selection of ascending or descending order for each key in composite primary key.
By default the order is set to ASC
. Valid values for the ORDER BY
clause are :asc
or :desc
or an array consisting of :asc
or :desc
and it’s case sensitive.
class User < ApplicationRecord
self.primary_key = [:first_name, :last_name]
end
# Users in ascending order of first_name and descending order of last_name
User.find_each(order: [:asc, :desc]) do |user|
puts "#{user.first_name} #{user.last_name}"
end
User Load (1.7ms) SELECT "users".* FROM "users" ORDER BY "users"."first_name" ASC, "users"."last_name" DESC LIMIT $1 [["LIMIT", 1000]]
Book Keeper
Oliver Smith
Sam Smith
Sam Admin
Varun Agarwal
Passing anything other than :asc
, :desc
raises ArgumentError
raise ArgumentError, ":order must be :asc or :desc or an array consisting of :asc or :desc, got #{order.inspect}"