如何确定调用方法的范围?

时间:2012-11-05 21:34:06

标签: ruby

我正在写一些类似于基准实用程序的东西,我很好奇是否有一种简单的方法来判断一个方法被调用的上下文。让我举例说明:

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称之为)的某种引用,这将很容易,但我不知道这是否可行,更不用说如何做了。有人能指出我正确的方向吗?

4 个答案:

答案 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包含classmodule并且可以直接大写,Y包含类或模块的名称。

否则我们直接使用方法名称,我们只需检查它是实例方法或对象方法。为此我们只检查self:如果它是Class的实例,那么我们调用一个类方法,否则我们调用一个实例方法。

<强>测试

在您的示例it gives the following output上:

  

在模块“Foo”的定义中调用
  在“Foo”类的定义中称为   在类方法“foo”运行期间调用   在实例方法“foo”的运行期间调用