This blog is part of our Rails 6 series. Rails 6.0.0.beta3 was recently released.

Rails 6 added implicit_order_column on ActiveRecord::ModelSchema which allows us to define a custom column for implicit ordering on model level. If there is no implicit_order_column defined, Rails takes primary key as implicit order column. Before Rails 6 too, primary key is used to order records implicitly by default.

This has impact on methods like first , last and many more where implicit ordering is used.

Let’s checkout how it works.

Rails 5.2

>> class User < ApplicationRecord
>>   validates :name, presence: true
>> end

=> {:presence=>true}

>> User.first
SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]

=> #<User id: 1, name: "Amit", created_at: "2019-03-11 00:18:41", updated_at: "2019-03-11 00:18:41">

>> User.last
SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]

=> #<User id: 2, name: "Mark", created_at: "2019-03-11 00:20:42", updated_at: "2019-03-11 00:20:42">

>> class User < ApplicationRecord
>>   validates :name, presence: true
>>   self.implicit_order_column = "updated_at"
>> end

=> Traceback (most recent call last):
        2: from (irb):10
        1: from (irb):12:in '<class:User>'
NoMethodError (undefined method 'implicit_order_column=' for #<Class:0x00007faf4d6cb408>)

Rails 6.0.0.beta2

>> class User < ApplicationRecord
>>   validates :name, presence: true
>> end

=> {:presence=>true}

>> User.first
SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]

=> #<User id: 1, name: "Amit", created_at: "2019-03-11 00:18:41", updated_at: "2019-03-11 00:18:41">

>> User.last
SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]

=> #<User id: 2, name: "Mark", created_at: "2019-03-11 00:20:42", updated_at: "2019-03-11 00:20:42">

>> class User < ApplicationRecord
>>   validates :name, presence: true
>>   self.implicit_order_column = "updated_at"
>> end

=> "updated_at"

>> User.find(1).touch
SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
UPDATE "users" SET "updated_at" = $1 WHERE "users"."id" = $2  [["updated_at", "2019-03-11 00:23:33.369021"], ["id", 1]]

=> true

>> User.first
SELECT "users".* FROM "users" ORDER BY "users"."updated_at" ASC LIMIT $1  [["LIMIT", 1]]

=> #<User id: 2, name: "Mark", created_at: "2019-03-11 00:20:42", updated_at: "2019-03-11 00:23:09">

>> User.last
SELECT "users".* FROM "users" ORDER BY "users"."updated_at" DESC LIMIT $1  [["LIMIT", 1]]

=> #<User id: 1, name: "Amit", created_at: "2019-03-11 00:18:41", updated_at: "2019-03-11 00:23:33">

Here is the relevant pull request.

Also note that in Rails 6 if UUID is used as primary key, created_at column is used by default for implicit ordering. Check out this pull request for more.