web-dev-qa-db-ja.com

Ruby requireで相対パスが機能しない理由

私はRubyの学習を始めていますが、私が理解していないことの1つは、なぜrequireディレクティブの相対パスがRubyで機能しないのかです。これは、私が現在使用しているほとんどすべてのスクリプト言語(JSP、PHP ...)で機能するものです。実際の例で説明します。 3つのクラスを含むshapesという名前のフォルダーがありますshaperectangle、およびsquare。クラスを呼び出してテストする別のファイルtest_shapes.rbもあります。次のようにクラスをメインファイルにインポートすると:

require "./shape"
require "./rectangle"
require "./square"

見つからないファイルに対してエラーが発生しました。このようにサブフォルダーの名前を含めると:

require "./shapes/shape"
require "./shapes/rectangle"
require "./shapes/square"

コードは完全に機能しています。プロジェクトのルートディレクトリ(私が思うにlibフォルダ)への完全なパスを指定したためです。含めるときは、次のようにハードディスクへの絶対パスを含めます。

require "#{File.dirname(__FILE__)}/shape"
require "#{File.dirname(__FILE__)}/rectangle"
require "#{File.dirname(__FILE__)}/square"

また、完全に機能しています。

したがって、最初のインポート方法(現在のフォルダーへの相対パス)が機能しない理由がわかっている場合は、説明が必要です。

22
Amaynut

相対パスは作業ディレクトリに基づいています。同じディレクトリにメインファイルがあると仮定します。プロジェクトルートでRuby ./shapes/main.rbを実行すると、Ruby {project_root}/shape.rbではなく{project_root}/shapes/shape.rbを見つけようとします。これは機能しません。

以下のようにrequire_relativeを使用する必要があります。

# {project_root}/shapes/main.rb
require_relative './shape'
require_relative './rectangle'
require_relative './square'
33
nacyot

相対パスを使用しています。そして、それらはスクリプトが実行される場所に関連しています。一般的には悪い考えです。 requireが実行される正確なファイルへの絶対パスまたは相対パスを使用する必要があります。

require File.expand_path("../shape", __FILE__)

PS: require_relative より簡潔に見える

6
fl00r

require(name)→trueまたはfalse指定された名前をロードし、成功した場合はtrueを、機能が既にロードされている場合はfalseを返します。

ファイル名が絶対パスに解決されない場合、$ LOAD_PATH($ :)にリストされているディレクトリで検索されます。

ファイル名の拡張子が「.rb」の場合、ソースファイルとしてロードされます。拡張子が「.so」、「。o」、「。dll」、または現在のプラットフォームのデフォルトの共有ライブラリ拡張子の場合、Rubyは共有ライブラリをRubyとしてロードします_拡張子。それ以外の場合、Rubyは、検出されるまで名前に「.rb」、「。so」などを追加しようとします。指定されたファイルが見つからない場合、LoadErrorが発生します。

Ruby拡張子の場合、指定されたファイル名には任意の共有ライブラリ拡張子を使用できます。たとえば、Linuxでは、ソケット拡張は「socket.so」であり、「socket.dll」がソケット拡張をロードする必要があります。

ロードされたファイルの絶対パスは、$ LOADED_FEATURES($ ")に追加されます。パスが既に$"にある場合、ファイルは再度ロードされません。たとえば、「a」が必要です。 require './a'はa.rbを再びロードしません。

require "my-library.rb" require "db-driver"ロードされたソースファイル内の定数またはグローバルは、呼び出し元プログラムのグローバル名前空間で利用可能になります。ただし、ローカル変数はロード環境に伝播されません。

require_relative(string)→trueまたはfalse Rubyは、必要なファイルのパスに対してstringという名前のライブラリをロードしようとします。ファイルのパスを特定できない場合、LoadErrorが発生します。ファイルがロードされるとtrueが返され、そうでない場合はfalseが返されます。

参照: http://Ruby-doc.org/core-2.1.2/Kernel.html#require-method

1
Vaibhav