我正在写一些类似于基准实用程序的东西,我很好奇是否有一种简单的方法来判断一个方法被调用的上下文。让我举例说明:
module Foo
my_method
class Foo
my_method
def self.foo
my_method
end
def foo
my_method
end
end
end
Foo::Foo.foo
Foo::Foo.new.foo
理想情况下,对于上述内容,“my_method”会打印如下内容:
在模块“Foo”的定义中调用 在“Foo”类的定义中调用 在类方法“foo”运行期间调用 在运行实例方法“foo”
期间调用
如果我可以获得对当前“范围”或上下文(或任何ruby称之为)的某种引用,这将很容易,但我不知道这是否可行,更不用说如何做了。有人能指出我正确的方向吗?
答案 0 :(得分:0)
Kernel#set_trace_func允许您定义跟踪过程(用于调试/分析目的)。例如:
class Foo
def self.foo
end
def foo
end
end
set_trace_func proc { |event, file, line, id, binding, classname|
printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
Foo.foo
Foo.new.foo
打印:
c-return foo.rb:11 set_trace_func Kernel
line foo.rb:13
call foo.rb:2 foo Foo
return foo.rb:3 foo Foo
line foo.rb:14
c-call foo.rb:14 new Class
c-call foo.rb:14 initialize BasicObject
c-return foo.rb:14 initialize BasicObject
c-return foo.rb:14 new Class
call foo.rb:5 foo Foo
return foo.rb:6 foo Foo
答案 1 :(得分:0)
试试这个:
Foo::Foo.method(:foo)
Foo::Foo.new.method(:foo)
答案 2 :(得分:0)
在方法内部定义中,使用__callee__
。直接在模块中,使用Module.nesting
。
答案 3 :(得分:0)
<强>解决方案强>
如果 only 要求检测模块定义,类定义和运行方法(类或实例方法)中的方法,那么您将使用以下内容:
def my_method
if ( a = /^.*?:\d*:in `(.*)'$/.match( caller[0] ) )
puts ( b = /^<(.*?):(.*?)>$/.match( a[1] ) ) ?
"Called in definition of #{b[1].capitalize} \"#{b[2]}\"" :
"Called during run of #{(self.is_a? Class) ? 'class' : 'instance'} method \"#{a[1]}\""
end
end
<强>分析强>
它使用包含堆栈跟踪的caller
。第一个正则表达式只解析调用者元素的语法:
[file]:[line]:in `<[type]:[name]>'
用于模块和类以及
[file]:[line]:in `[method]'
方法。
因此,第一个正则表达式删除了[file]:[line]:in
部分。
第二个检查是否存在<X:Y>
模式。
如果是,则表示X
包含class
或module
并且可以直接大写,Y
包含类或模块的名称。
否则我们直接使用方法名称,我们只需检查它是实例方法或对象方法。为此我们只检查self
:如果它是Class
的实例,那么我们调用一个类方法,否则我们调用一个实例方法。
<强>测试强>
在您的示例it gives the following output上:
在模块“Foo”的定义中调用
在“Foo”类的定义中称为 在类方法“foo”运行期间调用 在实例方法“foo”的运行期间调用