2012-10-15 77 views
9

對措辭不佳的問題表示歉意 - 不知道如何把它變得更好!我在ruby bar.rb執行bar.rb而不是foo.rb從包含的文件中,如何獲取包含文件的文件名?

foo.rb

module Foo 
    def filename 
    __FILE__ 
    end 
end 

bar.rb

require_relative 'foo' 
include Foo 

puts filename # outputs 'foo.rb' 

。這是一個庫函數,每次執行一些代碼時間,記錄的位置(和git REF)該代碼的。

+3

這是完全黑客,但['caller'](http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i- caller)方法可以讓你一些那裏的路。 'def filename; file = caller [0] .split(':'); [0]的文件; end'。 – Telemachus

+0

哈:)如果這是唯一的解決方案,我不會感到驚訝。 – seb

+0

它可能是,但它*仍然*感到哈克地獄。不得不以這種方式解析輸出只是犯規。 'caller'返回一個字符串數組,每個字符串的第一部分就是你想要的。根據你在做什麼,你可能需要考慮堆棧中你想看的地方。也就是說,您可能並不總是需要數組中的第一個條目。 – Telemachus

回答

4

你的問題激發我打開Ruby解釋器源代碼,看看__FILE__實際上是如何工作的。答案非常有趣:它在解析器內部實現。詞法分析器有一個特殊的令牌類型__FILE__。當解析器看到該令牌時,會將其轉換爲一個字符串常量,該常量包含解析器正在處理的文件的名稱。

從EXT /鬆土/ ripper.c的14948行:

case keyword__FILE__: 
return NEW_STR(rb_external_str_new_with_enc(ruby_sourcefile, strlen(ruby_sourcefile), 
         rb_filesystem_encoding())); 

我想這應該說清楚,試圖使__FILE__回報,包括文件的名稱是完全不可能的,除非你破解Ruby解釋器源代碼,或者編寫自己的預處理器,在將Ruby源代碼傳遞給解釋器之前,它將__FILE__轉換爲其他內容!

1

有一個技巧,你可能是一個能夠使用。如果您將方塊傳遞給方法,則可以使用方塊閉合來確定它的來源。例如:

def filename(&blk) 
    blk.eval "__FILE__" 
end 

但同樣,這意味着您必須通過一個塊。

老實說,我不知道你在做什麼,除了做一些常見的核心擴展方法之外,這可能是你真正不想做的事情。