File.expand_path(“../../ Gemfile”,__FILE__)这是如何工作的? 档案在哪里?

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

我只是试图从某个目录访问一个.rb文件,一个教程告诉我要使用这个代码,但是我不知道它是如何find这个gem文件的。

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

当你知道相对于当前文件的path时,获取文件的绝对path是一个有点丑陋的Ruby成语。 另一种书写方式是这样的:

 File.expand_path('../Gemfile', File.dirname(__FILE__)) 

两者都很丑,但是第一个变种更短。 然而,第一个变体在你掌握之前也是非常不直观的。 为什么额外.. ? (但第二个变体可能会提供一个线索,说明为什么需要)。

这是如何工作的: File.expand_path返回第一个参数相对于第二个参数(默认为当前工作目录)的绝对path。 __FILE__是代码所在文件的path。由于本例中的第二个参数是一个文件的path,而File.expand_path假定了一个目录,所以我们必须在path中添加一个额外的..以获得正确的path。 这是如何工作的:

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值,然后对于循环中的每一轮,将删除第一个..以及path组件之前。 先删除/file.rb/.. ,然后在下一轮/to/..被删除,我们得到/path/Gemfile

长话短说,当知道相对于当前文件的path时, File.expand_path('../../Gemfile', __FILE__)是获取文件绝对path的技巧。 在相对path中的额外的是消除__FILE__文件的名称。

两个参考:

  1. File :: expand_path方法文档
  2. __FILE__如何在Ruby中工作

今天我偶然发现了这个:

boot.rb提交在Rails的Github

如果从目录树中的boot.rb中find两个目录:

/ railties / lib目录/导轨/发电机/导轨/应用/模板

你会看到Gemfile,这导致我相信File.expand_path("../../Gemfile", __FILE__)引用下面的文件: /path/to/this/file/../../Gemfile File.expand_path("../../Gemfile", __FILE__) /path/to/this/file/../../Gemfile file File.expand_path("../../Gemfile", __FILE__)