Rails中的implicit_order_column和default_scope有什么区别?

What the difference between implicit_order_column and default_scope in Rails?

有什么区别:

self.implicit_order_column = 'id'

default_scope { order('id ASC') }

self.implicit_order_column 允许您使用另一列然后使用主键作为隐式排序列。这会影响 .first.last 等方法的工作方式:

User.class_eval do 
  self.implicit_order_column = 'created_at'
end

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

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

设置 self.implicit_order_column = 'id' 完全没有意义,因为无论如何默认值都是主键列。如果您提供明确的命令,当然不会使用 implicit_order_column。它实际上并没有改变从 class.

产生的任何其他作用域 另一方面,

default_scope 将默认范围附加到您从 class.

产生的任何范围
irb(main):001:0> User.all
   (0.5ms)  SELECT sqlite_version(*)
  User Load (0.1ms)  SELECT "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, role: "admin", created_at: "2020-11-08 19:31:31", updated_at: "2020-11-08 19:31:47">]>
irb(main):002:1* User.class_eval do
irb(main):003:1*   default_scope { order(id: :asc) }
irb(main):004:0> end
=> [#<Proc:0x00000000043703a8 (irb):3>]
irb(main):005:0> User.all
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, role: "admin", created_at: "2020-11-08 19:31:31", updated_at: "2020-11-08 19:31:47">]>
irb(main):006:0> 

这里的区别不是很明显。但是如果你认为在 SQL 世界中,没有 order 子句的查询将不会 return 确定顺序的记录(它的实现依赖)并且这里我们实际上是以确定的顺序获取记录。在许多 RDBMS 中,结果将很难区分,因为它们可能 return 按照修改顺序记录(如果他们喜欢的话)。

看起来很棒,直到你意识到 default_scope 是多么的不直观以及它会导致多少错误。

irb(main):006:0> User.all.order(:created_at)
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC, "users"."created_at" ASC LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, role: "admin", created_at: "2020-11-08 19:31:31", updated_at: "2020-11-08 19:31:47">]>
irb(main):007:0>

或者这个例子:

irb(main):001:1* User.class_eval do
irb(main):002:1*   default_scope { where(admin: true) }
irb(main):003:0> end
=> [#<Proc:0x0000000002bde460 (irb):2>]
irb(main):004:0> User.new
   (0.6ms)  SELECT sqlite_version(*)
=> #<User id: nil, role: "visitor", created_at: nil, updated_at: nil, admin: true>

哎呀! default_scope 因此被广泛认为是邪恶的。

参见: