Rails:如何从包含的关注中覆盖或私有化给定范围?
Rails: How to override or make private a given scope from an included Concern?
我担心在包含它的 ActiveRecord
class 中添加 scope
。大多数时候它的方式很好,但取决于 class 可能需要满足额外的标准。我不想重写模型中的范围,而是能够添加一个额外的标准方法。
这是我正在尝试做的事情:
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
这行得通,但是在 class 之外,您可以这样做:MyModel._my_scope
我想这没问题 - 也许有时我想要默认行为 - 但在这种情况下我不认为我这样做,我觉得封装 _my_scope
是要走的路。
我假设可以在 MyConcern
中创建一个私有的 class 方法,它包含在 MyModel
中,但这似乎不起作用,我也不是真的Concern
/mixin master 还不确定如何去做。另外, Concerns
是否被认为是混入?有区别吗?也很高兴知道。
您可以使用 class 方法实现范围的相同功能,您可以为这种情况继承和扩展这些功能。它与您的实施没有太大区别;只是通过使用 class 方法而不是范围来避免使用额外的 _ 方法。例如
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
对于问题的第二部分:从技术上讲,问题是 ruby Mixin;这只是 organize/group 仅作为关注点包含在您的模型中的 Mixins 的约定。使用 ActiveSupport::Concern 允许您向 Mixins 添加其他与模型相关的功能,例如范围、验证等,这是您无法使用普通模块获得的。
例如。你做不到
module MyConcern
scope :my_scope, ->(limit = nil) { _my_scope(limit) }
end
class MyModel < ApplicationRecord
include MyConcern # this will raise an error
end
我担心在包含它的 ActiveRecord
class 中添加 scope
。大多数时候它的方式很好,但取决于 class 可能需要满足额外的标准。我不想重写模型中的范围,而是能够添加一个额外的标准方法。
这是我正在尝试做的事情:
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
这行得通,但是在 class 之外,您可以这样做:MyModel._my_scope
我想这没问题 - 也许有时我想要默认行为 - 但在这种情况下我不认为我这样做,我觉得封装 _my_scope
是要走的路。
我假设可以在 MyConcern
中创建一个私有的 class 方法,它包含在 MyModel
中,但这似乎不起作用,我也不是真的Concern
/mixin master 还不确定如何去做。另外, Concerns
是否被认为是混入?有区别吗?也很高兴知道。
您可以使用 class 方法实现范围的相同功能,您可以为这种情况继承和扩展这些功能。它与您的实施没有太大区别;只是通过使用 class 方法而不是范围来避免使用额外的 _ 方法。例如
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
对于问题的第二部分:从技术上讲,问题是 ruby Mixin;这只是 organize/group 仅作为关注点包含在您的模型中的 Mixins 的约定。使用 ActiveSupport::Concern 允许您向 Mixins 添加其他与模型相关的功能,例如范围、验证等,这是您无法使用普通模块获得的。 例如。你做不到
module MyConcern
scope :my_scope, ->(limit = nil) { _my_scope(limit) }
end
class MyModel < ApplicationRecord
include MyConcern # this will raise an error
end