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.
1> User.find_each{|user| puts user.inspect} 2 3User 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.
1> User.find_each(order: :desc){|user| puts user.inspect} 2 3User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ? [["LIMIT", 1000]]
1> User.find_in_batches(order: :desc) do |users| 2> users.each do |user| 3> puts user.inspect 4> end 5> end 6 7User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ? [["LIMIT", 1000]]
1> User.in_batches(order: :desc) do |users| 2> users.each do |user| 3> puts user.inspect 4> end 5> end 6 7(0.2ms) SELECT "users"."id" FROM "users" ORDER BY "users"."id" DESC LIMIT ? [["LIMIT", 1000]] 8User 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.
1> User.find_in_batches(order: :DESC) do |users| 2> users.each do |user| 3> puts user.inspect 4> end 5> end 6 7Traceback (most recent call last): 8 2: from (irb):5 9 1: from (irb):6:in `rescue in irb_binding' 10ArgumentError (unknown keyword: :order)
Check out the pull request for more details.