requireとrequire_relativeとloadの違いをまとめておく
Rubyには、分割したソースコードを読み込む手段として
- require
- require_relative
- load
の三種類があります。
本記事では、これらの違いについてまとめていきます。
ディレクトリ構成
本記事では、以下のようなディレクトリ構成を想定します。
b/fuga.rb
class Fuga
def hello
puts 'Hello,world!'
end
end
a/foo.rb
puts "foo"
a/hoge.rbからこの2つのクラスの呼び出しを試みます。
require
正確には、 Kernel#require
というKernelモジュールで定義されたメソッドです。
このメソッドは、rubyコマンドの実行位置からのパスを参照します。※
a/hoge.rb
require './b/fuga'
obj = Fuga.new
obj.hello()
プロジェクトルートからhoge.rbをrubyコマンドで実行すると動作します。
ruby a/hoge.rb
ハマりがちな罠として、以下のように、aディレクトリでrubyコマンドを実行してしまうと動作しません。
cd a/
ruby hoge.rb # => cannot load such file -- ./b/fuga (LoadError)
ディレクトリa/からでは、./b/fuga.rbは存在しないからですね。
また、2回以上実行してもrequireは一回しか実行されません。
1回目の実行で正しく読み込めた場合はtrue,2回目以降の実行はfalse,ファイルが存在しない場合はLoadrrorを返します。
※ 正確には、グローバル変数$LOAD_PATHからのパスを参照します。詳しくはドキュメントを参照してください。
requite_relative
正確には、Kernel#require_relativeというKernelモジュールで定義されたメソッドです。
require_relativeが記述されたファイルの位置からの相対パスを参照します。
なので上記#requireの例と違い、このhoge.rbはプロジェクトルートからでも、a/ディレクトリに入っても実行することができます。
require_relative '../b/fuga' #hoge.rbからの相対パスを記述
obj = Fuga.new
obj.hello()
ruby a/hoge.rb => "Hello,World!"
cd a/
ruby hoge.rb => "Hello,World!"
requireと同じく1回しか実行されません。
1回目の実行で正しく読み込めた場合はtrue,2回目以降の実行はfalse,ファイルが存在しない場合はLoadrrorを返す点もrequireと同様です。
load
正確には、Kernel#loadというKernelモジュールで定義されたメソッドです。
パスの解決方法はrequireと同じく、rubyコマンドの実行位置からのパスを参照します。
requireとの違いは、2回以上実行できるということです。
require,require_relativeとの違いとして、 .rb拡張子の表記を省略できません。
a/hoge.rb
3.times.each do |_|
load './b/foo.rb' # "foo called"と3回表示される
end
requireとの使い分けとしては、クラス定義など一度読み込めばそれで充分であるものに対してはrequireを使用し、スクリプトの固まりなど、読み込んだときに逐次実行したいソースを読み込む場合にはloadを使用します。(実用上、loadよりもrequireのほうが使用頻度は多いです)
まとめ
3つのメソッドの違いをまとめると以下のようになります。
メソッド | パスの参照 | 対象ファイルの読み込み回数 | 拡張子の省略 |
---|---|---|---|
require | rubyコマンドを実行した位置からの相対パス($LOAD_PATH) | 1回のみ | 可 |
require_relative | require_relativeを呼び出した位置からの相対パス | 1回のみ | 可 |
load | rubyコマンドを実行した位置からの相対パス($LOAD_PATH) | 何回でも | 不可 |
Discussion