我正在尝试为类方法实现一个钩子,比如(version 1)
(allow default)
(deny network*)
和before_action
。问题是如果我在模块内定义一个方法,after_action
或define_method
内的def do_before; puts 'do_before called'; end
通常未定义。那么如何在method_added
内调用module method
?
method_added
答案 0 :(得分:1)
那是因为你正在使用
- extend
将指定模块的方法和常量添加到目标 元类
但您还需要 - include
它混合了指定模块的方法作为实例方法 目标类
# some code goes here
class Bar
extend Hooker
include Hooker
before_action 'foo2'
after_action 'bar2'
def my_func
puts 'MyFunc called'
end
end
Bar.new.my_func
=> before_action called with parameter foo2
=> after_action called with parameter bar2
=> do_before called
=> MyFunc called
=> do_after called
更明确的是将其与不同的模块分开。
答案 1 :(得分:0)
以下是另一种解决方案,您无需在课程中明确调用extend
和include
:
module Hooker
def self.included(klass)
klass.extend ClassMethods
end
module ClassMethods
[:before, :after].each do |element|
define_method("#{element}_action") do |name|
puts "#{element}_action called with parameter #{name}"
end
define_method("do_#{element}") do
puts "do_#{element} called"
end
end
end
def method_added(name)
return if @filtering # Don't add to original_ methods
@filtering = true
alias_method :"original_#{name}", name
define_method name do |*args|
do_before
self.send("original_#{name}", *args)
do_after
end
@filtering = false
end
end
class Bar
include Hooker
before_action 'foo2'
after_action 'bar2'
def my_func
puts 'MyFunc called'
end
end
Bar.new.my_func
这里的诀窍是Hooker
模块现在extend
虽然 include
。