QA@IT

Rubyのrequireで相対的にパスを指定する方法

10943 PV

現在、Rubyで自作クラスを読み込もうと相対パスを指定してrequireで読み込んでいるのですが、「cannot load such file 」になってしまいます。

具体的にソースで説明させていただきます。
まず前提として

  • rootfolder/db/main.rb
  • rootfolder/app/hoge.rb

という2つのファイルがあり、rootfolderから

ruby ./db/main.rb 

というコマンドを実行しているものとします。

main.rbのソースは以下の通りです。

require File.dirname(__FILE__) + '/../app/hoge.rb'

この結果

cannot load such file -- db/../app/hoge.rb (LoadError)

となってしまいます。

どうもFile.dirname(FILE)で得たパスよりも上の階層にいこうとするとエラーになるようです(下の階層にあるクラスを指定した場合は読み込めた)。
最悪絶対パスをハードコーディング(/User/…)みたいな書き方をすれば読み込めるんでしょうけど、どうも拡張性が低いきがするので極力使いたくありません。
何かいい方法はないでしょうか?

回答

質問にあるように ruby ./db/main.rb とした場合はエラーにならず、ruby db/main.rb としたときにエラーになったため、このケースについて書きます。

最初に解決方法です。
どちらでもかまいません。

# require_relative を使う
require_relative '../app/hoge.rb'
# File.expand_path で絶対パスにする
require File.expand_path(File.dirname(__FILE__) + '/../app/hoge.rb')

で、質問の状況で hoge.rb をロードできない理由は下記の通りです。

  • __FILE__ にはフルパスが入るわけではない
  • ruby db/main.rb としたとき main.rb 内では __FILE__ == "db/main.rb" になる
  • よって実行されるのは require "db/../app/hoge.rb"
  • require は、/ や . で始まらない場合、$LOAD_PATH を探索する
  • Ruby 1.9.2 以降は $LOAD_PATH にカレントディレクトリが含まれないので、hoge.rb は見つからない

ruby ./db/main.rb とした時は __FILE__ == "./db/main.rb" になるので、ロードできるわけです。どちらにしろやっかいなので、最初に挙げた 2 つの方法のいずれかを使うことをおすすめします。

編集 履歴 (0)
  • require_relativeなんていう便利なのがあったんですね。こちらで解決しました。ありがとうございます。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。