我希望能够在我的类中方法的开头和结尾插入一些代码。我也想避免重复。
我找到了 this answer有帮助,但对重复没有帮助。
class MyClass
def initialize
[:a, :b].each{ |method| add_code(method) }
end
def a
sleep 1
"returning from a"
end
def b
sleep 1
"returning from b"
end
private
def elapsed
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
block_value = yield
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
puts "elapsed: #{finish - start} seconds, block_value: #{block_value}."
block_value
end
def add_code(meth)
meth = meth.to_sym
self.singleton_class.send(:alias_method, "old_#{meth}".to_sym, meth)
self.singleton_class.send(:define_method, meth) do
elapsed do
send("old_#{meth}".to_sym)
end
end
end
end
以上确实有效,但更优雅的解决方案是什么?例如,我希望能够将 attr_add_code
放在类定义的开头,并列出我希望将代码添加到的方法,或者甚至可以指定我希望将它添加到所有 public方法。
注意:self.singleton_class
只是一种解决方法,因为我在初始化期间添加了代码。
最佳答案
如果重复是指要检测的方法列表,那么您可以执行以下操作:
module Measure
def self.prepended(base)
method_names = base.instance_methods(false)
base.instance_eval do
method_names.each do |method_name|
alias_method "__#{method_name}_without_timing", method_name
define_method(method_name) do
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
public_send("__#{method_name}_without_timing")
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
puts "Method #{method_name} took #{t2 - t1}"
end
end
end
end
end
class Foo
def a
puts "a"
sleep(1)
end
def b
puts "b"
sleep(2)
end
end
Foo.prepend(Measure)
foo = Foo.new
foo.a
foo.b
# => a
# => Method a took 1.0052679998334497
# => b
# => Method b took 2.0026899999938905
主要变化是我使用了prepend
并且在prepended
回调中你可以找到在类上定义的方法列表instance_methods(false)
,false
参数表示不应考虑祖先。
关于ruby - 如何将 "magically"代码添加到ruby中的所有公共(public)类方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56508425/