This blog is part of our Rails 6.1 series.

Before Rails 6.1, batch processing methods like find_each, find_in_batches and in_batches didn’t support the ORDER BY clause. By default the order was set to id ASC.

> User.find_each{|user| puts user.inspect}

User Load (0.4ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1000]]

Rails 6.1 now supports ORDER BY id for ActiveRecord batch processing methods like find_each, find_in_batches, and in_batches. This would allow us to retrieve the records in ascending or descending order of ID.

> User.find_each(order: :desc){|user| puts user.inspect}

User Load (0.4ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1000]]
> User.find_in_batches(order: :desc) do |users|
>   users.each do |user|
>     puts user.inspect
>   end
> end

User Load (0.3ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1000]]
> User.in_batches(order: :desc) do |users|
>   users.each do |user|
>     puts user.inspect
>   end
> end

(0.2ms)  SELECT "users"."id" FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1000]]
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ?  [["id", 101]]

Points to remember:

  • The ORDER BY clause only works with the primary key column.
  • Valid values for the ORDER BY clause are [:asc,:desc] and it’s case sensitive. If we use caps or title case (like DESC or Asc) then we’ll get an ArgumentError as shown below.
> User.find_in_batches(order: :DESC) do |users|
>   users.each do |user|
>     puts user.inspect
>   end
> end

Traceback (most recent call last):
        2: from (irb):5
        1: from (irb):6:in `rescue in irb_binding'
ArgumentError (unknown keyword: :order)

Check out the pull request for more details.