requireとrequire_relativeとloadの違いをまとめておく[Ruby]







Rubyには、分割したソースコードを読み込む手段として

  • require
  • require_relative
  • load

の三種類があります。

本記事では、これらの違いについてまとめていきます。

実行環境

本記事では、以下のようなディレクトリ構成を想定します。

b/fuga.rb

class Fuga
  def hello
    puts 'Hello,world!'
  end
end

b/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) 何回でも 不可