Ruby 1.9.2が「。」を削除する理由 LOAD_PATHから、そして代替は何ですか?


154

Ruby 1.9.2の最新のチェンジセットでは、現在のディレクトリがの.一部になりませんLOAD_PATH。私はそれ.がの一部であると想定しているRakefileの重要な数を持っているLOAD_PATHので、これはそれらを壊しました(プロジェクトパスに基づくすべてのrequireステートメントで「ロードするファイルがありません」と報告されました)。これを行う正当な理由はありましたか?

修正に関しては、$: << "."どこにでも追加することは機能しますが、信じられないほどハックに思え、私はそれをしたくありません。Rakefiles 1.9.2+と互換性を持たせるための好ましい方法は何ですか?

回答:


141

これは「セキュリティ」リスクと見なされました。

絶対パスを使用して回避できます

File.expand_path(__FILE__) et al

またはやって

require './filename' (ironically).

またはを使用して

require_relative 'filename'

または「include」ディレクトリを追加する

ruby -I . ...

または、irbを使用して同じ。

$irb -I .

27
使って巻きましたrequire_relative。ありがとう。
John Feminella、2010年

11
これは、実行可能ファイルを実行するためのパスに現在のディレクトリを含まないほとんどのUNIXに似ていますか?
Andrew Grimm、

5
require './filename'スクリプトが実行されているのと同じディレクトリに設定された作業ディレクトリでスクリプトが実行された場合にのみ機能します。これは多くの場合、マルチディレクトリプロジェクトには当てはまりません。
mxcl 2012

34

2つの理由があります。

  • 堅牢性と
  • 安心

どちらも同じ基本原理に基づいています。一般に、コードを実行すると、現在のディレクトリが何であるかがわかりません。つまり、ファイルが必要で、そのファイルが現在のディレクトリにあることに依存している場合、そのファイルが存在するかどうか、または実際に存在するはずのファイルかどうかを制御する方法はありません。


5
2つのファイルを互いに同じ場所に配置することを強制することは、必ずしも悪い要件ではないと思います。それが本当なら、ディレクトリを使用する必要はありません。
John Feminella、

4
@John Feminella:これは、ファイルを相互に相対的なパスに配置することとどう関係していますか?問題は、それらを.、つまり現在の作業ディレクトリに対して相対的に配置することです。ユーザーcdが別のディレクトリに移動すると、現在の作業ディレクトリが変更され、ユーザーがスクリプトを呼び出したときのディレクトリに応じて、require 完全に異なるファイルになります。それは良い考えではないと思います。
イェルクWミッターク

適切なインターフェイスを維持するには、これを行う必要がありますか?$: << File.dirname(__FILE__)
ジョシュアチーク

4
@ジョシュア・チーク:個人的に、私はそれが好きではありません。(しかし、それはそのようなもので散らかされているので、私の古いコードを見ないでください:-))。私は単にふりというlibディレクトリが上にあり$LOAD_PATH、その後requireに比べてすべてのファイルlib。つまり、$LOAD_PATH正しく設定する方法を理解するのは管理者に任せます。RubyGemsを使用する場合、RubyGemsが自動的にそれ行うため、それは簡単です。Debian パッケージを使用する場合は、パッケージメンテナーの仕事です。全体として、それはかなりうまくいくようです。
イェルクWミッターク

8
@Joshua Cheek:また、Ruby 1.9.2 .$LOAD_PATH、からの削除に対する一種の相殺として、現在実行中のファイルの場所(つまり)に対する相対的なrequire_relative...驚き... requiresaファイルを導入していますFile.dirname(__FILE__)
イェルクWミッターク

16

他の回答が指摘するように、.ロードパスDir.pwdでは現在ロードされているファイルのディレクトリではなく、現在の作業ディレクトリを参照するため、セキュリティリスクになります。したがって、スクリプトを実行している人は誰でもcd、別のディレクトリに移動するだけでこれを変更できます。良くない!

__FILE__代替として構築されたフルパスを使用しています。

require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))

とは異なりrequire_relative、これはRuby 1.8.7との下位互換性があります。


4
この変化は、(私は個人的に読みやすく見つけた)もあります: require Pathname.new(__FILE__).dirname + 'filename'
タイラーリック

8

使用する require_relative 'file_to_require'

これをコードにスローして、1.8.7でrequire_relativeを機能させます。

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller.first), path.to_str)
    end
  end
end


3

いくつかのことに気づくまで、これは混乱を招く変化であることがわかりました。

.profile(Unix)にRUBYLIBを設定して、以前と同じように処理を続行できます。

export RUBYLIB="."

しかし、前述のように、そうすることは安全ではないと長い間考えられてきました。

ほとんどの場合、先頭に「。」を付けてRubyスクリプトを呼び出すだけで問題を回避できます。例:./scripts/server。


3

JörgW Mittagが指摘したrequire_relativeように、使用したいのは、必要なファイルがrequire現在の作業ディレクトリではなく、宣言のソースファイルに関連しているためだと思います。

依存関係は、rakeビルドファイルに対して相対的である必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.