ActiveRecord条件覆盖和default_scope

时间:2015-07-17 00:05:52

标签: ruby-on-rails ruby activerecord

无论如何都要覆盖default_scope或之前的范围? (除了重构模型以不使用default_scope或使用unscoped)

任何人都知道,为什么这种方式有效?这感觉不是最期望或最直观的结果。

样品:

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

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

关于default_scope,您只需要知道一件事,就是这样:不要使用它。

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

default_scope说“不”。