【问题标题】:What the difference between implicit_order_column and default_scope in Rails?Rails 中的implicit_order_column 和default_scope 有什么区别?
【发布时间】:2020-12-20 08:38:53
【问题描述】:

有什么区别:

self.implicit_order_column = 'id'

default_scope { order('id ASC') }

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-6


    【解决方案1】:

    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 $1  [["LIMIT", 1]]
    
    User.last
    # => SELECT "users".* FROM "users" ORDER BY "users"."updated_at" DESC LIMIT $1  [["LIMIT", 1]]
    

    设置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>
    

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

    见:

    【讨论】:

    • 这是一个陷阱:不幸的是,implicit_order_column 仅适用于对象本身的范围,而不适用于关联,因此即使 class Whisker; self.implicit_order_column = 'timestamp' 也需要指定 class Cat; has_many :whiskers, -&gt; { order(timestamp: "asc") } -- iirc default_scope也适用于关联
    猜你喜欢
    • 2021-08-16
    • 2012-06-15
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    相关资源
    最近更新 更多