self.implicit_order_column
允许您使用另一列,然后使用主键作为隐式排序列。这会影响方法的方式,例如.first
and .last
work:
User.class_eval do
self.implicit_order_column = 'created_at'
end
User.first
# => SELECT "users".* FROM "users" ORDER BY "users"."updated_at" ASC LIMIT $1 [["LIMIT", 1]]
User.last
# => SELECT "users".* FROM "users" ORDER BY "users"."updated_at" DESC LIMIT $1 [["LIMIT", 1]]
Setting self.implicit_order_column = 'id'
完全没有意义,因为无论如何默认值都是主键列。这implicit_order_column
如果您提供明确的命令,当然不会使用。它实际上并没有改变该类产生的任何其他作用域。
default_scope
另一方面,将默认范围附加到您从类中生成的任何范围。
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 子句的查询将不会按确定的顺序返回记录(取决于其实现),而这里我们实际上是按确定的顺序获取记录。在许多 RDBMS 中,结果很难区分,因为它们可能会按照修改的顺序返回记录(如果它们愿意的话)。
看起来很棒,直到你意识到多么不直观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>
Yikes! default_scope
因此被广泛认为是邪恶的。
See:
- https://github.com/rails/rails/pull/34480 https://github.com/rails/rails/pull/34480
- https://rails-bestpractices.com/posts/2013/06/15/default_scope-is-evil/ https://rails-bestpractices.com/posts/2013/06/15/default_scope-is-evil/
- https://www.reddit.com/r/rails/comments/ha6gqj/default_scope_is_evil/ https://www.reddit.com/r/rails/comments/ha6gqj/default_scope_is_evil/