Project

General

Profile

Bug #11205

Updated by nobu (Nobuyoshi Nakada) almost 9 years ago

~~~ 
 Kernel#__dir__ 

 Returns the canonicalized absolute path of the directory of the file from which this method is called. It means symlinks in the path is resolved. If __FILE__ is nil, it returns nil. The return value equals to File.dirname(File.realpath(__FILE__)). 
 ~~~ 
 Here is a script that shows the problem. 

 ~~~ruby ~~~ 
 def mytest(&block) 
   ret = block.binding.eval( '[ __FILE__, __dir__ ]' ) 
   assert_equal("bill", __dir__) 
 end 
 dir = __dir__ 
 eval(%q( 
   ret = mytest { } 
   ret[0] == '/bill/bill' 
   ret[1] == dir            # where it shoudl == '/bill' 
   #  
 ), nil, '/bill/bill', 1) 

 ~~~ 
 Even without the binding problem it is clear from the current ruby tests that  
 `__dir__` `\_\_dir__` is not equal to `File.realpath(__FILE__)`. `File.realpath(\_\_FILE__)`.  

 ~~~ 
   def test___dir__ 
     assert_instance_of String, __dir__ 
     assert_equal(File.dirname(File.realpath(__FILE__)), __dir__) 
     bug8436 = '[ruby-core:55123] [Bug #8436]' 
     assert_equal(__dir__, eval("__dir__", binding), bug8436) 
     bug8662 = '[ruby-core:56099] [Bug #8662]' 
     assert_equal("arbitrary", eval("__dir__", binding, "arbitrary/file.rb"), bug8662) 
     assert_equal("arbitrary", Object.new.instance_eval("__dir__", "arbitrary/file.rb"), bug8662) 
   end 
 ~~~ 
 possible solution: 
 Fix `eval` so that it never affects `Kernel#__dir__` and add a `Kernel#__file__` method and rewrite the description as: 

 ~~~ 
 Kernel#__dir__ 

 Returns the canonicalized absolute path of the directory of the file from which this method is called. It means symlinks in the path is resolved. The return value equals to File.dirname(File.realpath(__file__)). 

 ~~~ 
 And a definition for `__file__` `\_\_file__` 

 ~~~ 
 Kernel#__file__ 

 Returns the canonicalized absolute path of the directory of the file from which this method is called. It means symlinks in the path is resolved. The return value equals to File.dirname(File.realpath(__file__)). 
 Note: __file__ is equal to __FILE__ except inside of #eval and #eval_instance. 
 ~~~ 

 This assumes that the purpose of `__dir__` `\_\_dir__` is to find files in the current filesystem, and not for the purpose of debugging. 

Back