File.expand_path(“ ../../Gemfile”、__FILE__)これはどのように機能しますか?ファイルはどこにありますか?


84

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

あるディレクトリから.rbファイルにアクセスしようとしていますが、チュートリアルでこのコードを使用するように指示されていますが、gemファイルがどのように検出されているのかわかりません。


回答:


194
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__))。


2
Ruby 1.9.2より前のバージョンとの非互換性以外に、「require_relative」だけを使用すべきではない理由はありますか?
— ダニーアンドリュース

9
Ruby 2.0以降、使用できますFile.expand_path('../Gemfile',__dir__)
— Phrogz 2016年

Theoからのこの行は、ディレクトリではありませんがFile.expand_path assumes a directory、ついにクリックしてくれました__FILE__。意味のあるものについて__dir__は、実際にはディレクトリです。
— mbigras 2018年

9

2つの参照:

  1. File :: expand_pathメソッドのドキュメント
  2. __FILE__Rubyではどのように機能しますか

私は今日これに出くわしました:

RailsGithubでのboot.rbコミット

ディレクトリツリーのboot.rbから2つのディレクトリに移動する場合:

/ railties / lib / rails / generators / rails / app / templates

Gemfileが表示されます。これにより、File.expand_path("../../Gemfile", __FILE__)次のファイルを参照していると思います。/path/to/this/file/../../Gemfile


投稿ありがとうございますが、これはgembundlerチュートリアルからのものだったので、彼らがどのようにそれを持っていたかを正確に理解しようとしていました:)
— thenengah 2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.