【问题标题】:ActiveRecord condition override and default_scopeActiveRecord 条件覆盖和 default_scope
【发布时间】:2015-07-17 00:05:52
【问题描述】:

有没有办法在 where 条件下覆盖默认范围或以前的范围? (除了重新构建模型以不使用default_scope 或使用无作用域)

另外,为什么会这样工作的原因是什么?感觉这不是最令人期待或最直观的方法。

示例:

class Product < ActiveRecord::Base
  default_scope -> { visible }
  scope :visible, -> { where(visible: true) }
  scope :hidden, -> { where(visible: false) }
end

当我这样做时:

Product.hidden

生成的 sql 尝试匹配两个值:

WHERE "products"."visible" = 't' AND "products"."visible" = 'f'

没有 default_scope 也是如此:

class Product < ActiveRecord::Base
  scope :visible, -> { where(visible: true) }
  scope :hidden, -> { where(visible: false) }
end

当我这样做时:

Product.visible.where(visible: false)

或者当我这样做时:

Product.visible.hidden

生成的 sql 尝试匹配两个值:

WHERE "products"."visible" = 't' AND "products"."visible" = 'f'

我用一个完整的测试用例提出了这个要点:https://gist.github.com/mmontossi/dcf71457e98a169c28a5

当我第一次问这个问题时,我认为这是一个错误: https://github.com/rails/rails/issues/20907#issuecomment-122131096

【问题讨论】:

  • 要点没有解释所需的行为?
  • stackoverflow.com/questions/1834159/… 重复的问题。这个问题的答案有很好的解释
  • 我刚刚编辑了这个问题,我想找出为什么会这样的原因。感觉很奇怪,但也许这是保持这种状态的好理由。
  • 您链接的问题非常好,但我没有找到有关为什么这样设计的信息。
  • 它做你想做的事。您声明了默认范围。默认范围每次都运行(不包括您使用无范围的)。这就是为什么默认范围真的很难看的原因。它们每次都会被执行,在这种情况下它似乎没用,但你对你的代码负责。

标签: ruby-on-rails ruby activerecord


【解决方案1】:

关于default_scope,您只需要了解一件事,那就是:不要使用它。

default_scope 就像毒品一样。起初感觉很棒,一切似乎都更容易了,但随着时间的推移,你意识到使用它是一个坏主意。到那时为时已晚,你必须永远处理后果。好吧,这并不完全正确:您可以简单地停止使用 default_scope 并重写您的控制器以显式调用实际范围,这是您首先应该做的,因为这样很明显正在检索哪些数据并且因此对于其他开发人员(包括将来会忘记使用default_scope)的开发人员来说不会那么混乱。所以default_scope 并不像吸毒那么糟糕。只是有时会有这种感觉。

default_scope说“不”。

【讨论】:

  • 我认为删除 default_scope 或将其重构为 default_order 会有所改进。拥有它但不使用它感觉很奇怪。
  • 很难完全删除功能。 default_scope 已经存在了一段时间并且(我假设)被广泛使用。老实说,这并没有我想象的那么糟糕——我有点半开玩笑。但它是那些看起来像真正节省时间的功能之一,但往往会变成真正的时间浪费,尤其是当新编码人员加入团队时。
  • 我知道你在开玩笑,但我是认真的,我认为在以后的版本中添加到 Rails 中会是一个很好的约定。默认情况下,一个干净的模型,如果你想要更具体的东西,选择或组合你想要的范围,默认情况下只决定顺序,如果你以后改变主意,你可以使用 reorder 方法。
【解决方案2】:

要覆盖默认范围,请使用unscoped 方法:Product.unscoped.hidden

添加条件的原因是代码完全按照您的要求执行:运行默认范围,然后指定任何自定义条件。

【讨论】:

    猜你喜欢
    • 2010-12-22
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    相关资源
    最近更新 更多