module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
module ClassMethods
...
end
end
通过使用ActiveSupport::Concern,上面的模块可以写成:
require 'active_support/concern'
module M
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
class_methods do
...
end
end
此外,它优雅地处理模块依赖关系。给定一个Foo模块和一个依赖于前者的Bar模块,我们通常会写如下:
module Foo
def self.included(base)
base.class_eval do
def self.method_injected_by_foo
...
end
end
end
end
module Bar
def self.included(base)
base.method_injected_by_foo
end
end
class Host
include Foo # We need to include this dependency for Bar
include Bar # Bar is the module that Host really needs
end
但是Host为什么要关心Bar的依赖关系,即Foo呢?我们可以尝试直接将Foo隐藏在Bar中:
module Bar
include Foo
def self.included(base)
base.method_injected_by_foo
end
end
class Host
include Bar
end
require 'active_support/concern'
module Foo
extend ActiveSupport::Concern
included do
def self.method_injected_by_foo
...
end
end
end
module Bar
extend ActiveSupport::Concern
include Foo
included do
self.method_injected_by_foo
end
end
class Host
include Bar # It works, now Bar takes care of its dependencies
end
2条答案
按热度按时间cigdeys31#
https://api.rubyonrails.org/classes/ActiveSupport/Concern.html:
一个典型的模块看起来像这样:
通过使用
ActiveSupport::Concern
,上面的模块可以写成:此外,它优雅地处理模块依赖关系。给定一个
Foo
模块和一个依赖于前者的Bar
模块,我们通常会写如下:但是
Host
为什么要关心Bar
的依赖关系,即Foo
呢?我们可以尝试直接将Foo
隐藏在Bar
中:不幸的是,这是行不通的,因为当包含
Foo
时,它的基础是Bar
模块,而不是Host
类。使用ActiveSupport::Concern
,模块依赖关系可以正确解决:nr9pn0ug2#
使用ActiveSupport::关注常规mixin的一个原因是它延迟加载包含。因此,如果您引用模型、控制器等中的代码,它将解析。然而,当加载mixin时,您可能会得到未定义的错误。