我编写了一个模块来在实例方法调用之前或之后挂接方法。我想将这些钩子应用于从父类继承的所有类。但是,如果我在父类中编写该钩子,它将不会被执行,只有在子类中存在钩子时,它才会被执行。
这是创建钩子的模块:
module Hooks
def self.included(base)
base.send :extend, ClassMethods
end
module ClassMethods
# everytime we add a method to the class we check if we must redifine it
def method_added(method)
if @hooker_before && (@methods_to_hook_before.include?(method)|| @methods_to_hook_after.include?(method)) && !@methods_seen.include?(method)
hooked_method_before = instance_method(@hooker_before) if @hooker_before
hooked_method_after = instance_method(@hooker_after) if @hooker_after
@methods_to_hook_before.each do |method_name|
begin
method_to_hook = instance_method(method_name)
rescue NameError => e
return
end
@methods_seen.push(method)
define_method(method_name) do |*args, &block|
hooked_method_before.bind(self).call if hooked_method_before
method_to_hook.bind(self).(*args, &block) ## your old code in the method of the class
hooked_method_after.bind(self).call if hooked_method_after
end
end
end
end
def before(*methods_to_hook, hookers)
@methods_to_hook_before = methods_to_hook
@methods_to_hook_after = [] unless @methods_to_hook_after
@hooker_before = hookers[:call]
@methods_seen = []
end
def after(*methods_to_hook, hookers)
@methods_to_hook_after = methods_to_hook
@methods_to_hook_before = [] unless @methods_to_hook_before
@hooker_after = hookers[:call]
@methods_seen = []
end
end
end
module Utilities
def before_generate
puts("in before generate utilities")
end
end
class Parent
include Utilities
include Hooks
def generate
puts("in generate Parent")
end
end
class Child < Parent
before :generate, call: :before_generate
def generate
puts("in child generate")
end
end
class AnotherChild < Parent
before :generate, call: :before_generate
def generate
puts("in child generate")
end
end
Child.new.generate()
产生所需的输出:
在生成实用程序之前
在儿童产生
但是,我希望从Parent继承的所有类都自动从此行为继承。将before :generate, call: :before_generate
添加到父类将无法解决问题。是否可以通过将所有子类包装在同一模块中的方法?
有没有一种方法可以实现这一目标,或者我应该在每个需要的子类中重现before调用。