This blog is part of our Rails 6 series.
Rails 6 added implicit_order_column on ActiveRecord::ModelSchema which allows us to define a custom column for implicit ordering on the model level. If there is no implicit_order_column defined, Rails takes a primary key as the implicit order column. Also, before Rails 6, the primary key was 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
1>> class User < ApplicationRecord 2>> validates :name, presence: true 3>> end 4 5=> {:presence=>true} 6 7>> User.first 8SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]] 9 10=> #<User id: 1, name: "Amit", created_at: "2019-03-11 00:18:41", updated_at: "2019-03-11 00:18:41"> 11 12>> User.last 13SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1 [["LIMIT", 1]] 14 15=> #<User id: 2, name: "Mark", created_at: "2019-03-11 00:20:42", updated_at: "2019-03-11 00:20:42"> 16 17>> class User < ApplicationRecord 18>> validates :name, presence: true 19>> self.implicit_order_column = "updated_at" 20>> end 21 22=> Traceback (most recent call last): 23 2: from (irb):10 24 1: from (irb):12:in '<class:User>' 25NoMethodError (undefined method 'implicit_order_column=' for #<Class:0x00007faf4d6cb408>)
Rails 6.0.0.beta2
1>> class User < ApplicationRecord 2>> validates :name, presence: true 3>> end 4 5=> {:presence=>true} 6 7>> User.first 8SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]] 9 10=> #<User id: 1, name: "Amit", created_at: "2019-03-11 00:18:41", updated_at: "2019-03-11 00:18:41"> 11 12>> User.last 13SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1 [["LIMIT", 1]] 14 15=> #<User id: 2, name: "Mark", created_at: "2019-03-11 00:20:42", updated_at: "2019-03-11 00:20:42"> 16 17>> class User < ApplicationRecord 18>> validates :name, presence: true 19>> self.implicit_order_column = "updated_at" 20>> end 21 22=> "updated_at" 23 24>> User.find(1).touch 25SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 26UPDATE "users" SET "updated_at" = $1 WHERE "users"."id" = $2 [["updated_at", "2019-03-11 00:23:33.369021"], ["id", 1]] 27 28=> true 29 30>> User.first 31SELECT "users".* FROM "users" ORDER BY "users"."updated_at" ASC LIMIT $1 [["LIMIT", 1]] 32 33=> #<User id: 2, name: "Mark", created_at: "2019-03-11 00:20:42", updated_at: "2019-03-11 00:23:09"> 34 35>> User.last 36SELECT "users".* FROM "users" ORDER BY "users"."updated_at" DESC LIMIT $1 [["LIMIT", 1]] 37 38=> #<User id: 1, name: "Amit", created_at: "2019-03-11 00:18:41", updated_at: "2019-03-11 00:23:33"> 39
Here is the relevant pull request.