我有一些类,其方法会在进入和退出方法时进行记录,如下所示:
<br/>
def methodName1(args)
@logger.debug(">>#{<strong>callee</strong>}")
...
@logger.debug("<<#{<strong>callee</strong>}")
end
def methodName2(args)
@logger.debug(">>#{<strong>callee</strong>}")
...
@logger.debug("<<#{<strong>callee</strong>}")
end
我想知道是否有一种元编程方法可以用记录器调用包围这些方法? 这将涉及识别我希望首先包围的类中的所有方法,然后再包围它们。
一个
最佳答案
我倾向于在类前面添加一个动态创建的匿名模块,其实例方法使用 super
在打印方法入口消息后调用同名类的实例方法在打印方法退出消息之前。
让我们首先创建一个具有两个实例方法的类,一个在调用时传递一个 block 。
class C
def mouse(nbr_mice, impairment)
puts "%d %s mice" % [nbr_mice, impairment]
end
def hubbard(*args)
puts yield args
end
end
C.ancestors
#=> [C, Object, Kernel, BasicObject]
c = C.new
c.mouse(3, 'blind')
# 3 blind mice
c.hubbard('old', 'mother', 'hubbard') { |a| a.map(&:upcase).join(' ') }
# OLD MOTHER HUBBARD
现在我们构造一个方法来创建匿名模块并将其添加到类中。
def loggem(klass, *methods_to_log)
log_mod = Module.new do
code = methods_to_log.each_with_object('') { |m,str| str <<
"def #{m}(*args); puts \"entering #{m}\"; super; puts \"leaving #{m}\"; end\n" }
class_eval code
end
klass.prepend(log_mod)
end
我们现在已准备好调用此方法,其参数等于模块要添加到的类以及要记录的该类的实例方法。
loggem(C, :mouse, :hubbard)
C.ancestors
#=> [#<Module:0x007fedab9ccf48>, C, Object, Kernel, BasicObject]
c = C.new
c.method(:mouse).owner
#=> #<Module:0x007fedab9ccf48>
c.method(:mouse).super_method
#=> #<Method: Object(C)#mouse>
c.method(:hubbard).owner
#=> #<Module:0x007fedab9ccf48>
c.method(:hubbard).super_method
#=> #<Method: Object(C)#hubbard>
c.mouse(3, 'blind')
# entering mouse
# 3 blind mice
# leaving mouse
c.hubbard('old', 'mother', 'hubbard') { |a| a.map(&:upcase).join(' ') }
# entering hubbard
# OLD MOTHER HUBBARD
#leaving hubbard
参见 Module::new和 Module#prepend .
关于ruby - 使用元编程来包围类中的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42952705/