我想用日志记录包装模块的所有类方法,如下所示:
module SomeModule
def self.foo
puts "bar"
end
class << self
SomeModule.methods(false).each do |method|
alias_method "old_#{method}".to_sym, method
define_method method do |*args|
puts "Called method: #{method}"
send "old_#{method}", *args
end
end
end
end
SomeModule.foo
#-> Called method: foo
#-> bar
完美无缺。但是如果我想要在我调用方法时才发生包装呢?当你打电话
时,我怎么能做到这一点module SomeModule
def self.foo
puts "bar"
end
def self.add_logging_to_all_methods
#???
end
end
SomeModule.add_logging_to_all_methods
SomeModule.foo
#-> Called method: foo
#-> bar
答案 0 :(得分:1)
我不会问你想要的是什么,但现在是:
module SomeModule
def self.foo
puts "bar"
end
def self.add_logging_to_all_methods
eigenclass = class << self; self; end
methods(false).each do |method|
eigenclass.class_eval do
alias_method "old_#{method}".to_sym, method
define_method method do |*args|
puts "Called method: #{method}"
send "old_#{method}", *args
end
end
end
end
end
SomeModule.add_logging_to_all_methods
SomeModule.foo
请注意,这也会向add_logging_to_all_methods
添加“日志记录”,但仅在调用它之后,所以如果您只调用一次,则不应该看到任何错误。
eigenclass
的含义是添加此方法foo
和add_logging_to_all_methods
的“实例”。通过在self
块内返回class << self; end
,我正在获取该实例。然后我要求在该实例的上下文中对块进行求值,该实例与先前的方法大致相同。
可能有一种更简单的方法。
答案 1 :(得分:1)
您可以在所有课程中应用它:
ObjectSpace.each_object.select { |o| o.is_a? Class }.each do |klass|
klass.class_eval do
methods(false).each do |method|
alias_method "old_#{method}".to_sym, method
define_method method do |*args|
puts "Called method: #{method}"
send "old_#{method}", *args
end
end
end rescue nil
end
答案 2 :(得分:0)
啊没关系,只是放置整个班级&lt;&lt;方法中的自我阻止工作正常。