Submitted by Paul Brannan (Mon Feb 09 15:02:05 UTC 2004)
Consider the following code:
a.rb:
puts "a"</pre> b.rb:
require 'a' puts "b"</pre> test.rb:
require './a' require './b'</pre>
This will print:
a
a b</pre>
because a.rb is loaded first by the name 'a.rb' and then by the name './a.rb'. This is probably not what is intended, and the only workarounds are:
The above code is probably not a good idea to begin with (requring files from the current directory is bad, in case the user runs from a different directory than expected), but it is a simple way to demonstrate the problem.
def find_file_in_path(file, path=$:, extensions=['', '.so', '.rb'])
path.each do |dir| pathname = File.join(dir, file) extensions.each do |ext| filename = pathname + ext if File.exists?(filename) then return File.expand_path(filename) end end end return file
end
def realpath(file)
if not File.respond_to?(:readlink) then return file end total = '' File.expand_path(file).split(File::SEPARATOR).each do |piece| next if piece == "" if File.symlink?(total + File::SEPARATOR + piece) then total += File::SEPARATOR + piece begin total = File.expand_path( File.readlink(total), File.dirname(total)) end while File.symlink?(total) else total << File::SEPARATOR + piece end end return total
end
$__old_require__ = method(:require)
def require(file)
file_to_require = find_file_in_path(file) $__old_require__.call(realpath(file_to_require))
end
Comments | Current voting | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
RCRchive copyright © David Alan Black, 2003-2005.
Powered by .
I'd also like to see __FILE__ normalised in this way. While researching an RCR that I'm preparing, I found the following:
I have C:/home/x/x.rb:
I also have C:/home/x/y/x.rb:
If I run from C:/home/x, I get:
Changing the require in C:/home/x/x.rb to "x/y/x.rb" and running from C:/home, I get:
Restoring the require to "y/x.rb" and running from C:/home with "ruby -Ic:/home/x" shows:
Same, but from C:\Windows ("ruby -I\home\x \home\x\x.rb"):
This seems a bit ... ugly. I'm not completely sure that __FILE__ itself should be fully resolved, but it seems that there's something odd here.
--Austin
The API for "require" is
not .
Although the implementation concatenate the feature name and path in $LOAD_PATH variable to find loading library file, it does not stop being feature name. When you require two libraries "a" and "./a", they might be different just because you're requiring two different features.
But I'm going to store full path used to load a library in the $" variable (but no normalization), to implement requiring libraries relative from __FILE__.
-- matz.