我担心会将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吗?有区别吗?知道这也很好。
答案 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