I have written a module to hook methods before or after an instance method call. Id like to apply these hooks to all classes that inherit from the parent class. However if I write the hook in the parent class it wont be executed, it will only be executed if it is present in the child class.
This is the module to create the hooks :
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()
produces the desired output :
in before generate utilities
in child generate
However I would like all class that inherits from Parent to automatically inherit from this behavior. Adding before :generate, call: :before_generate
to the parent class won't do the trick. Is there maybe a way by wrapping all the child classes in the same module ?
Is there a way to achieve that or shall I reproduce the before call in every single child class where I want it.