ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
我只是想从某个目录访问.rb文件,一个教程告诉我使用此代码,但我看不到它如何找到gem文件。
Answers:
File.expand_path('../../Gemfile', __FILE__)
是一个丑陋的Ruby惯用法,用于在您知道相对于当前文件的路径时获取文件的绝对路径。另一种写法是:
File.expand_path('../Gemfile', File.dirname(__FILE__))
两者都很丑陋,但第一个变体较短。但是,第一个变体在您不了解它之前也非常不直观。为什么要额外..
?(但第二个变体可能会提示为什么需要它)。
它是这样工作的:File.expand_path
返回第一个参数相对于第二个参数的绝对路径(默认为当前工作目录)。__FILE__
是代码所在的文件的路径。由于在这种情况下,第二个参数是文件的路径,并File.expand_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
将首先获取value /path/to/file.rb/../../Gemfile
,然后对于循环中的每一回合,..
将删除第一回合,以及位于其之前的路径组件。首先/file.rb/..
被删除,然后在下一轮/to/..
被删除,我们得到/path/Gemfile
。
长话短说,这File.expand_path('../../Gemfile', __FILE__)
是一个技巧,当您知道相对于当前文件的路径时,获取文件的绝对路径。..
相对路径中的多余项是消除了中的文件名__FILE__
。
在Ruby 2.0中,有一个Kernel
称为的函数__dir__
,该函数的实现为File.dirname(File.realpath(__FILE__))
。
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directory
尽管__FILE__
不是目录,但Theo的这一行终于让我点击了。为了使事情有意义,请使用__dir__
实际上是目录。
两个参考:
我今天偶然发现了这一点:
如果从目录树中的boot.rb上找到两个目录:
/ railties / lib / rails / generators / rails / app / templates
您会看到Gemfile,这使我相信File.expand_path("../../Gemfile", __FILE__)
引用了以下文件:/path/to/this/file/../../Gemfile