2012-10-15 181 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 

但同样,这意味着您必须通过一个块。

老实说,我不知道你在做什么,除了做一些常见的核心扩展方法之外,这可能是你真正不想做的事情。