Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

From an included file, how can I get the filename of the file doing the including?

Tags:

ruby

Apologies for the poorly worded question title - no idea how to put it better!

In the following code, when I execute ruby bar.rb, how can I make it output bar.rb, rather than foo.rb?

In foo.rb:

module Foo
  def filename
    __FILE__
  end
end

In bar.rb:

require_relative 'foo'
include Foo

puts filename # outputs 'foo.rb'

This is for a library function that, each time some code is executed, records the location (and git ref) of that code.

like image 384
seb Avatar asked Oct 15 '12 11:10

seb


2 Answers

Your question stimulated me to crack open the Ruby interpreter source and see how __FILE__ actually works. The answer is pretty interesting: it's implemented right inside the parser. The lexer has a special token type for __FILE__. When the parser sees that token, it converts it to a string constant, which contains the name of the file the parser is working on.

From line 14948 of ext/ripper/ripper.c:

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

I think this should make it clear that trying to make __FILE__ return the name of the including file is completely impossible, unless you hack the Ruby interpreter source, or write your own preprocessor which transforms __FILE__ to something else before passing the Ruby source to the interpreter!

like image 59
Alex D Avatar answered Oct 22 '22 06:10

Alex D


There is a trick you might be a able to use. If you pass a block to the method you could use the blocks closure to determine it's source. Something like:

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

But again, that means you have to pass a block.

Honestly I wonder what you are trying to accomplish, b/c outside of make some common core extension method, this is probably something you really don't want to do.

like image 32
trans Avatar answered Oct 22 '22 07:10

trans