为什么 "File.expand_path(...)" 解决的问题与我预期的不同?

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

我目前正在逐句查看 gitlab_development_kit gem 的代码,看看它是如何工作的。

我目前在 this line of code,我已经在线上方和下方放置了一个调试器点。

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

我检查了 $LOAD_PATHFile.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"

我输入next来推进调试器,然后重新检查上面的值:

(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", ...]

如果 File.expand_path('../../lib', __FILE__) 的值真的是 "/Users/richiethomas/Workspace/ThreeEasyPieces/lib",那么这就是我希望预先附加到 $LOAD_PATH 的值。但是相反,它看起来像是来自 RBENV 管理的 gem 版本的 lib 目录被预先挂起。这是什么恶魔魔法? :-)

提示中的

__FILE__ 与文件中的 __FILE__ 计算的值不同。其实__FILE__就是当前正在执行的文件,但是在交互提示下,并没有当前正在执行的文件,所以,__FILE__只是一个占位符。

在 IRb 中,__FILE__ 计算为 '(irb)',在 Pry 中,它计算为 '(pry)',在 Byebug 中,它计算为 '(byebug)':

(byebug) __FILE__
"(byebug)"

因为 (byebug) 是一个完全合法的文件名,File.expand_path 将使用当前工作目录来扩展它。例如。如果当前工作目录是 /a/b/cFile.expand_path(__FILE__) 将计算为 /a/b/c/(byebug)。因此,

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

然后将扩展到

'/a/b/lib'