【问题标题】:How to create a scope that is unscoped in Rails 5?如何在 Rails 5 中创建一个没有作用域的作用域?
【发布时间】:2016-11-01 19:03:32
【问题描述】:
class Foo < ActiveRecord::Base
  default_scope { where(active: false) }

  scope :include_deleted, -> { unscoped }

这不起作用。它返回作用域文档。

alias_method :include_deleted, :unscoped

这也不起作用:undefined method 'unscoped'

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

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

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

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

【问题讨论】:

    标签: ruby-on-rails activerecord ruby-on-rails-5 scoping


    【解决方案1】:

    为确保清除默认范围,您可以像这样取消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 }
    

    【讨论】:

      【解决方案2】:

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

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

      附:首先使用default_scope 通常是个坏主意。但是关于它的文章很多,所以我不会在这里推理。

      【讨论】:

      • 我收到了undefined method 'unscope' for Foo:Class。但是您链接到的源代码应该这样做......
      • @BSeven 我认为这是不可能的。如果您查看我提供的文档,您会发现它适用于 Rails 5.x,因此它应该可以正常工作。例如在控制台中试一试
      • @BSeven 你玩了吗?您也可以尝试使用 { unscope(where: :column_name) } 来获取任意数量的 column_names..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-23
      • 2019-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多