ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
我只是想从某个目录中访问一个.rb文件,一个教程告诉我使用这个代码,但我看不到它是如何找到gem文件的。
答案 0 :(得分:182)
File.expand_path('../../Gemfile', __FILE__)
是一种有点丑陋的Ruby习惯用法,用于在知道相对于当前文件的路径时获取文件的绝对路径。另一种写作方式是:
File.expand_path('../Gemfile', File.dirname(__FILE__))
两者都很难看,但第一个变种更短。然而,第一个变体在你掌握它之前也是非常不直观的。为什么额外..
? (但第二个变体可能提供了为什么需要它的线索。)
这是它的工作原理:File.expand_path
返回第一个参数的绝对路径,相对于第二个参数(默认为当前工作目录)。 __FILE__
是代码所在文件的路径。由于这种情况下的第二个参数是文件的路径,而File.expand_path
假设一个目录,我们必须多加{{1}在路径中获得正确的路径。这是它的工作原理:
..
基本上是这样实现的(在以下代码中File.expand_path
的值为path
,而../../Gemfile
的值为relative_to
) :
/path/to/file.rb
(还有一点,它将def File.expand_path(path, relative_to=Dir.getwd)
# first the two arguments are concatenated, with the second argument first
absolute_path = File.join(relative_to, path)
while absolute_path.include?('..')
# remove the first occurrence of /<something>/..
absolute_path = absolute_path.sub(%r{/[^/]+/\.\.}, '')
end
absolute_path
end
扩展到主目录,依此类推 - 上面的代码可能还有一些其他问题)
逐步调用~
上方的代码将首先获得值absolute_path
,然后对于循环中的每一轮,将删除第一个/path/to/file.rb/../../Gemfile
以及路径组件在它之前。第一个..
被删除,然后在下一轮/file.rb/..
被移除,我们得到/to/..
。
简而言之,当您知道相对于当前文件的路径时,/path/Gemfile
是获取文件绝对路径的技巧。相对路径中的额外File.expand_path('../../Gemfile', __FILE__)
是在..
中删除文件的名称。
在Ruby 2.0中,有一个名为__FILE__
的{{1}}函数,实现为Kernel
。
答案 1 :(得分:9)
两个参考文献:
__FILE__
work in Ruby 今天我偶然发现了这个:
boot.rb commit in the Rails Github
如果你从目录树中的boot.rb上升了两个目录:
/railties/lib/rails/generators/rails/app/templates
你看到Gemfile,这让我相信File.expand_path("../../Gemfile", __FILE__)
引用了以下文件:/path/to/this/file/../../Gemfile