ruby picture

RCR 250: absolute __FILE__

Submitted by neoneye (Sat May 01 07:05:30 UTC 2004)

Abstract

Make __FILE__ an absolute path. Currently __FILE__ reflects the path which the program were invoked with. It's always easy get a relative path from an absolute one, but not the other way!

Problem

__FILE__ is vulnerable to chdir. Many people make global variables containing the expanded path, before they start doing file manipulation. Thats kludgy, however if they didn't do anything they would have a fragile program.

Proposal

Make __FILE__ robust, so that one can rely on that it always contains a absolute path.

Analysis

This will break the widespread 'if $0 == __FILE__' ideom, see [>rubytalk:98831] for discussion of $0 and __FILE__. It will for sure break many other places, which assumes the old concept.

Implementation

I don't know what to write here.
ruby picture
Comments Current voting

I'm one of the people who does write code that stores the expanded path (hopefully) before another library calls chdir. I do find this to be a kludge, and I wish there were a better way.

However, breaking existing code is not an acceptable solution, especially when there are alternatives. One such alternative is to use a different variable, perhaps__EXPANDED_FILE__.

Also, regarding the if $0 == __FILE__' idiom, this idiom tends to confuse newcomers to Ruby and imo it should be done away with in favor of something a little cleaner. Something I've been playing with:

  require 'caller_helpers'
  require 'realpath'  def main
    file, lineno, method = parse_caller(caller[0])
    caller_file = caller_file_pathname(file)
    if realpath(caller_file) == realpath($0) then
      yield
    end
  end

(for this to work you will need caller_helpers.rb and realpath.rb from Now I can write:

  require 'main'
  #  
  main do
    puts "This is only executed if the file is run from the command line, not if"
    puts "it is required from another script."
  end

I think the implementation of the main() method is even kludgier than the if $0 == __FILE__' idiom, but the implementation could be replaced if a new version of the interpreter had support for implementing it a better way. The implementation given here can then be used only on older versions of the interpreter, if a program or library needs to be backward-compatible.

I haven't bothered to submit an RCR for this, because I don't yet know if I like the name of the method (my co-workers have had to get me to explain what the code does, which is a hint that it's not sufficiently self-documenting).

-- Paul Brannan


Two thoughts:
- changing __FILE__ will break a lot of code
- __FILE__ is ugly anyway.

Why not just abandon __FILE__ and stick the stuff in a module? This was suggested by someone else on ruby-talk:

System.current_file     # same as __FILE__
System.current_filepath # expanded version

Many other useful methods/constants could be stuck in the System module; and we'd be another step of the way towards getting rid of Ruby's "Perl compatibility layer". :)

--Mark Hubbart


I have personally been bitten quite savagely by this, umm, feature and found it quite difficult to work around.

I doubt if much code would be broken if the semantics of __FILE__ was tweaked in this manner, but if it concerns people __ABSOLUTE_FILE__ would be find by me.


Strongly opposed 2
Opposed 1
Neutral 2
In favor 1
Strongly advocate 0
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .