Ruby(2.2.0)を使っていて自作したファイルを読み込み(require)する際にハマったのでメモ。
結論から言えば自作ファイルを読み込ませる際は相対パスで読み込むrequire_relativeを使うのが良さそう。
ファイル構成と読み込み
ファイル構成
/app
|- main.rb # <- 実行ファイル
|- controller.rb
|- /modules
| |- a.rb
| |- b.rb
| |- /dir
| |- e.rb
|- /lib
|- c.rb
|- d.rb
読み込み順
main.rb # <- 実行ファイル
|- controller.rb ... (1)
|- /modules/a.rb ... (2)
|- /modules/b.rb ... (3)
| |- /modules/dir/e.rb ... (4)
| |- /lib/d.rb ... (5)
|- /lib/c.rb ... (5)
1. 実行ファイルから同一階層のファイルの読み込み (main.rb -> controller.rb)
main.rb
からcontroller.rb
を読み込みます。
require は ./
が無いとエラーになる
require 'controller.rb'
Ruby1.9.2から./
が無いとエラーになる仕様になったらしい。
require './controller.rb'
※ただし、実行ファイルが別階層のものになると./
有りでもエラーになる
require_relative で指定する場合 ./
無しでもOKっぽい
require_relative 'controller.rb'
require_relative './controller.rb'
requireでもrequire_relativeでも/
からファイルを指定するとエラーになる場合がある
/
からファイルやディレクトリを指定すると、完全なルートからファイルを探すっぽいのでルートからのパスと一致してない場合はエラーになるっぽい。
require '/controller.rb'
/app/controller.rbなので、/controller.rbは見つからないっぽい?
それとも仕様的にNGなのかちょっと不明。
require_relative
でも/
からファイル指定するとルートからファイル検索するっぽい。
require_relative '/controller.rb'
2. 同一階層のフォルダ内のファイルの読み込み (controller.rb -> /modules/a.rb)
main.rb
で読み込むcontroller.rb
で、同一階層にある/modules
フォルダ内のa.rb
を読み込ませます
同一階層のファイルの読み込みと同じ
require 'modules/a.rb'
require './modules/a.rb'
※ただし、実行ファイルが別階層のものになると./
有りでもエラーになる
require_relative 'modules/a.rb'
require_relative './modules/a.rb'
3. 実行ファイルと同じ階層にあるフォルダ内でもファイル読み込み (/modules/a.rb -> /modules/b.rb)
先のcontroller.rb
で読み込む/modules/a.rb
から同じ/modules
ディレクトリ内のファイルを読み込ませる
main.rb # 実行ファイル
/modules
|- a.rb # -> b.rb を読み込ませたい
|- b.rb
require は 実行ファイルからの絶対パスでないとエラーになる
require 'b.rb'
./
を付けてもa.rb
からの相対パスなので読み込めない
require './b.rb'
main.rb
からのパスを指定すればOK
require './modules/b.rb'
※ただし、実行ファイルが別階層のものになると、当然パスが変わるのでエラーになる
相対パス読み込み require_relative
require_relative 'b.rb'
require_relative './b.rb'
4. フォルダ内のファイルから同一フォルダに有るディレクトリ内のファイルの読み込み (/modules/b.rb
-> /modules/dir/e.rb
)
/modules/b.rb
から/modules/dir/e.rb
を読み込む
main.rb # 実行ファイル
/modules
|- b.rb # -> ./dir/e.rb を読み込ませたい
|- /dir
|- e.rb
require
なら実行ファイルからの絶対パスで指定する
require './modules/dir/e.rb'
※ただし、実行ファイルが別階層のものになると、当然パスが変わるのでエラーになる
require_relative
の場合は相対パスで指定する
require_relative 'dir/e.rb'
require_relative './dir/e.rb'
5. 別階層のディレクトリにあるファイルの読み込み (/modules/a.rb -> /lib/c.rb, /modules/b.rb
-> /lib/d.rb
)
/modules/a.rb
から/lib/c.rb
を読み込む
main.rb # 実行ファイル
/modules
|- a.rb # -> /lib/b.rb を読み込ませたい
/lib
|- c.rb
require
なら実行ファイルからの絶対パス、require_relative
なら読み込ませるファイル(a.rb
)からの相対パスで指定すればOK。
/modules/b.rb
から/lib/d.rb
を読み込ませるのも同様。
require './lib/c.rb'
※ただし、実行ファイルが別階層のものになると、当然パスが変わるのでエラーになる
require_relative '../lib/c.rb'
まとめ
require
... 実行ファイルからの絶対パスで指定。必ず./
から始める必要があるっぽい。
require_relative
... そのファイルからの相対パスで指定。
自作したファイルを読み込ませる場合は、
require_relativeで相対パスでファイル指定をする 方法が間違い無さそうだなと思いました。
[参考]