Rails:如何从包含的关注点中覆盖给定范围或将给定范围设为私有?

时间:2019-05-23 13:30:54

标签: ruby-on-rails named-scope activesupport-concern

我担心会将scope添加到包含它的ActiveRecord类中。在大多数情况下,情况都不错,但根据班级的不同,可能还需要满足其他条件。我不想重写模型中的范围,而只需要添加一个额外的条件方法即可。

这就是我想要做的:

module MyConcern
  extend ActiveSupport::Concern

  included do
    # I've included the fact I pass a limit variable here because my scope also does this, in case that's relevant for solving this.
    # I'd like this to be private or not accessible via `MyModel._my_scope`
    scope :_my_scope, ->(limit = nil) { (joins, wheres, order etc etc).limit(limit) }
    scope :my_scope, ->(limit = nil) { _my_scope(limit) }
  end
end

class MyModel < ApplicationRecord
  include MyConcern

  # Including the "private" scope to add my extra criteria.
  scope :my_scope, ->(limit = nil) { _my_scope(limit).where(foo: 'bar') }
end

class AnotherModel < ApplicationRecord
  include MyConcern

  # I like the default behavior here so nothing else to do
end

这是可行的,但是您可以在类之外执行以下操作:MyModel._my_scope我想还可以-也许有一段时间我想使用默认行为-但在这种情况下,我不认为我愿意感觉就像封装_my_scope一样。

我假设可以在MyConcern中创建一个私有类方法,该方法包含在MyModel中,但这似乎不起作用,而且我并不是真正的Concern / mixin master还不知道如何执行此操作。另外,Concerns被认为是mixins吗?有区别吗?知道这也很好。

1 个答案:

答案 0 :(得分:1)

您可以使用类方法实现作用域的相同功能,在这种情况下可以继承和扩展。它与您的实现没有太大不同;只是通过使用类方法而不是范围来避免使用多余的_方法。例如

module MyConcern
  extend ActiveSupport::Concern

  class_methods do
    def my_scope(limit = nil)
      (joins, wheres, order etc etc).limit(limit)
    end
  end
end

class MyModel < ApplicationRecord
  include MyConcern

  def self.my_scope(limit = nil)
    super.where(foo: 'bar')
  end
end

class AnotherModel < ApplicationRecord
  include MyConcern
end

对于您的问题的第二部分:从技术上讲,关注点是红宝石Mixin。只是作为关注事项来组织/分组模型中包含的Mixins的约定。使用ActiveSupport :: Concern可以将其他与Model相关的功能添加到Mixins中,例如范围,验证等,这是使用常规模块无法获得的。 例如。你做不到

module MyConcern
  scope :my_scope, ->(limit = nil) { _my_scope(limit) }
end

class MyModel < ApplicationRecord
  include MyConcern # this will raise an error
end