April 16, 2019
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.
>> 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>)
>> 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.
If this blog was helpful, check out our full blog archive.