File.expand_path(“../../ Gemfile”,__ FILE__)这是如何工作的?文件在哪里?

时间:2010-12-17 21:31:47

标签: ruby

ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)

我只是想从某个目录中访问一个.rb文件,一个教程告诉我使用这个代码,但我看不到它是如何找到gem文件的。

2 个答案:

答案 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)

两个参考文献:

  1. File::expand_path method documentation
  2. How does __FILE__ work in Ruby
  3. 今天我偶然发现了这个:

    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