2012-11-05 32 views
1

我正在寫某種類似於基準測試實用程序的東西,而且我很好奇是否有一種簡單的方法可以告訴從哪種上下文中調用方法。讓我舉例說明:如何確定調用方法的範圍?

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」的

的運行中調用的運行中調用。如果我能得到一些參考目前的「範圍」或CON文本(或任何紅寶石稱它)這將是容易的,但我不知道這是甚至可能的,更不用說如何做到這一點。任何人都可以將我指向正確的方向嗎?

回答

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 
+0

我看到了set_trace_func,但解析出來似乎很笨拙。是否沒有內置$ current_scope的東西? –

0

試試這個:

Foo::Foo.method(:foo) 
Foo::Foo.new.method(:foo) 
0

內方法的定義,使用__callee__。直接在模塊內使用Module.nesting

0

解決方案

如果您要求檢測模塊定義,類定義中的方法和運行方法(類或實例方法),那麼你會喜歡的東西下面去:

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

在類的定義「富」
稱爲模塊「富」
定義調用類的方法「富的運行中調用「
在實例方法」富「運行期間調用