在使用ActiveSupport::Concern时,如果我们在一个类中定义了多个included块,当我们包含这个模块时,只会执行最后一个included块。这与官方文档所述有所不同,因此需要进行调整。
示例代码如下:
require 'active_support/concern'
module MyConcern
extend ActiveSupport::Concern
included do
puts "XXX"
end
included do
puts "YYY"
end
end
class MyClass
include MyConcern
end
在该示例中,我们定义了一个MyConcern模块并使用了两个included块,分别输出XXX和YYY。然而,当我们包含这个模块时,只会输出YYY,没有输出XXX。
为了使它按照我们定义的顺序执行每个included块,我们可以使用alias_method_chain方法。具体方法如下:
require 'active_support/concern'
module MyConcern
extend ActiveSupport::Concern
included do
ActiveSupport::Deprecation.warn("This syntax is deprecated and will not be supported in future versions of Rails.", caller(1))
end
# 改写的部分开始
module ClassMethods
def included(base = nil, &block)
if base.nil?
ActiveSupport::Deprecation.warn("Calling `included` without an argument was deprecated in Rails 5.0. To continue using `included` without arguments, you must define it as `included(base)`.", caller(1))
instance_eval(&block) if block_given?
else
super
end
end
def included_with_inheritance(base = nil, &block)
included_without_inheritance(base, &block)
klass = base || self
klass.inherited_callbacks.each do |callback|
klass.define_callbacks callback, inheritable_callbacks_options
end
end
alias_method_chain :included, :inheritance
end
#改写的部分结束
included do
puts "XXX"
end
included do
puts "YYY"
end
end
class MyClass
include MyConcern
end
在这个改写后的示例中,我们重定义了included方法。我们加入了一个新的included_with_inheritance方法来拦截在类中定义的included块。然后我们使用alias_method_chain方法将它们链接到共同执行。
这样改写后,当我们包含这个模块时,就会按照我们定义的