Rubyのrequireにディレクトリ名が必要な理由

Rubyのrequireのパス - imHo

Cだと、ソースがどこにあっても

#include "hoge.h"

とやればそのファイル自身のパスも含めて探してくれるので便利なんだけどRubyの場合含めて
くれないので、あるライブラリ的なソースから別のライブラリを参照するときにその置き場所
に困る。例えばソースが

・ main.rb
・ lib/lib1.rb
・ lib/lib2.rb

とあって main.rbからlib1.rbがrequireされてて、lib1.rbからlib2.rbがrequireされてるとし
て、lib1.rb 中で

require './lib2'

としても読めなくてエラーになる。

これの仕様には理由がある。
たとえばrcodetoolsの場合、以下のような配置になっている。

lib/rcodetools/xmpfilter.rb
lib/rcodetools/options.rb

ここで、options.rbを読み込むには「require 'rcodetools/options'」とする必要があるのだが、それはそれとして利点でもある。なぜなら、foo/options.rbなんてライブラリを使う場合、「require 'options'」とするとロードパス依存になってしまうから、かえって問題になる。逆にディレクトリ名も指定するおかげでoptionsという一般的な名前のライブラリ名もつけられるのだ。

[2008/05/28]追記

相対requireならば、使われていますよ。たとえばactive_support.rbはこんなふうになっています。ファイル構成は「lib/active_support.rb」、「lib/active_support/vendor.rb」〜となっていて、「require 'active_support'」とすると「lib/active_support」以下のライブラリが一度にrequireされます。

$:.unshift(File.dirname(__FILE__))

require 'active_support/vendor'
# 以下延々とrequireが続く。

「$:.unshift(File.dirname(__FILE__))」がミソですね。現在のRubyスクリプトディレクトリをロードパスの先頭に加えるという決まり文句で、Cプリプロセッサの「#include "〜"」相当です。

[2008/05/28]追記

Kernel#requireを乗っ取って「require 'http://〜'」を実現するライブラリ‥どこかにありましたね。名前は失念。だけどセキュリティ的に怖いです…もしそのURLの先にファイルを削除するようなのが含まれているかと思えば…