如何创建一个在 Rails 5 中没有作用域的作用域?

How to create a scope that is unscoped in Rails 5?

class Foo < ActiveRecord::Base
  default_scope { where(active: false) }

  scope :include_deleted, -> { unscoped }

这不起作用。它 returns 范围文档。

alias_method :include_deleted, :unscoped

这也不行:undefined method 'unscoped'

那么,如何定义一个没有作用域的作用域?

用例:是的,我知道我可以使用 unscoped。让我试着解释一下为什么它可能不是一个好主意。有充分的理由定义另一个具有相同功能的范围。原因是它使代码更易于理解,并且使我的意图更加明确。 unscoped 不会告诉 reader 任何有关默认范围的信息。它只会带来更多问题。如果我们可以定义另一个范围来解释 为什么我们使用范围 ,那么它会为 reader 提供上下文并帮助他们理解代码。

顺便说一句,我看到了一些相关的 SO 问题,但它们已经过时了。所以这道题是关于Rails5。这使得它与众不同,不是重复的

使用 Mongoid 5,但我认为这不会改变答案。

您可以使用 ActiveRecord::QueryMethods#unscope:

scope :include_deleted, -> { unscope(:where) }

P.S。首先使用 default_scope 通常不是一个好主意。但是关于它的文章太多了,我就不在这里推理了。

为确保清除默认范围,您可以取消 where 子句的范围,如下所示:

scope :deleted, -> { unscope(where: :active).where(active: false) }
scope :without_deleted, -> { where(active: true) }
scope :with_deleted, -> { unscope(where: :active) }
default_scope { without_deleted }

我更喜欢使用名为 deleted_at 的时间戳列。这样我就可以标记删除时间。在这种情况下,范围将如下所示:

scope :deleted, -> { unscope(where: :deleted_at).where.not(deleted_at: nil) }
scope :without_deleted, -> { where(deleted_at: nil) }
scope :with_deleted, -> { unscope(where: :deleted_at) }
default_scope { without_deleted }