Rails 6 adds implicit_order_column

Amit Choudhary

Amit Choudhary

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.

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.

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.