Search code examples
rubyrubygemsrbenv

Why is "File.expand_path(...)" resolving to something different from what I expect?


I'm currently stepping through the code of the gitlab_development_kit gem to see how it works.

I'm currently at this line of code, and I've placed a debugger point above and below the line.

    3: require 'byebug'
    4: byebug
    5: 
=>  6: $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
    7: byebug
    8: require 'gitlab_development_kit'

I inspect the values of $LOAD_PATH and File.expand_path('../../lib', __FILE__):

(byebug) $LOAD_PATH
["/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash", ...]

(byebug) File.expand_path('../../lib', __FILE__)
"/Users/richiethomas/Workspace/ThreeEasyPieces/lib"

I type next to advance the debugger, and then re-check the above values:

(byebug) next

[2, 11] in /Users/richiethomas/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/gitlab-development-kit-0.2.5/bin/gdk
    2: require 'yaml'
    3: require 'byebug'
    4: byebug
    5: 
    6: $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
=>  7: byebug
    8: require 'gitlab_development_kit'
    9: 
   10: 
   11: 

(byebug) File.expand_path('../../lib', __FILE__)
"/Users/richiethomas/Workspace/ThreeEasyPieces/lib"

(byebug) $LOAD_PATH
["/Users/richiethomas/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/gitlab-development-kit-0.2.5/lib", "/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash", ...]

If the value of File.expand_path('../../lib', __FILE__) really was "/Users/richiethomas/Workspace/ThreeEasyPieces/lib", then that's what I would expect to be pre-pended to $LOAD_PATH. But instead, it looks like the lib dir from the version of the gem managed by RBENV was pre-pended instead. What kind of devil's magic is this? :-)


Solution

  • __FILE__ at the prompt does not evaluate to the same value as __FILE__ in the file. In fact, __FILE__ is the currently executing file, but at the interactive prompt, there is no currently executing file, ergo, __FILE__ is just a placeholder.

    Within IRb, __FILE__ evaluates to '(irb)', within Pry, it evaluates to '(pry)', and within Byebug, it evaluates to '(byebug)':

    (byebug) __FILE__
    "(byebug)"
    

    Since (byebug) is a perfectly legal filename, File.expand_path will expand it using whatever the current working directory is. E.g. if the current working directory is /a/b/c, File.expand_path(__FILE__) will evaluate to /a/b/c/(byebug). Ergo,

    File.expand_path('../../lib', __FILE__)
    

    will then expand to

    '/a/b/lib'