ruby - 使用元编程来包围类中的方法

标签 ruby metaprogramming

我有一些类,其方法会在进入和退出方法时进行记录,如下所示: <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::newModule#prepend .

关于ruby - 使用元编程来包围类中的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42952705/

相关文章:

ruby - 如何使 Ruby 脚本每秒运行一次?

ruby - 在 Ruby 中使用 str.to_f 时如何确定数值?

ruby - 类与 Class.new,模块与 Module.new

Ruby - Rails - Savon 结构 SOAP XML 主体

ruby - 在 Ruby 中,$?是一个不能直接赋值的 'read-only' 变量。知道如何为我自己的自定义变量/类执行此操作吗?

c++ - 是否可以在编译时检测函数是否被调用

c# - 哪些资源解释了 C# 中的反射和元编程?

ruby - 如何使用元编程来减少此 Ruby 代码中的冗余?

ruby - 定义 "method_called".. 如何制作一个钩子(Hook)方法,每次调用类的任何函数时都会调用该方法?

Ruby 以编程方式生成 lambda