ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
あるディレクトリから.rbファイルにアクセスしようとしていますが、チュートリアルでこのコードを使用するように指示されていますが、gemファイルがどのように検出されているのかわかりません。
回答:
File.expand_path('../../Gemfile', __FILE__)
現在のファイルからの相対パスがわかっている場合にファイルへの絶対パスを取得するための、やや醜いRubyイディオムです。それを書く別の方法はこれです:
File.expand_path('../Gemfile', File.dirname(__FILE__))
どちらも醜いですが、最初のバリアントは短いです。ただし、最初のバリアントは、コツをつかむまでは非常に直感的ではありません。なぜ余分なのか..ですか?(しかし、2番目のバリアントはそれが必要な理由についての手がかりを与えるかもしれません)。
仕組みは次のとおりですFile.expand_path。2番目の引数(デフォルトでは現在の作業ディレクトリ)を基準にした、最初の引数の絶対パスを返します。__FILE__はコードが含まれるファイルへのパスです。この場合の2番目の引数はファイルへのパスであり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最初に値が取得され/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__。意味のあるものについて__dir__は、実際にはディレクトリです。
2つの参照:
私は今日これに出くわしました:
ディレクトリツリーのboot.rbから2つのディレクトリに移動する場合:
/ railties / lib / rails / generators / rails / app / templates
Gemfileが表示されます。これにより、File.expand_path("../../Gemfile", __FILE__)次のファイルを参照していると思います。/path/to/this/file/../../Gemfile