QA@IT

Rubyでrequireよりloadを使うべき場面は?

10147 PV

requireだと、ロードするファイルのファイル名に .rbや.soという拡張子を明示的に書かなくても良くて、ロードパスにあるファイルをロード対象として探してくれるというのは分かります。loadは相対、絶対にかかわらずパス指定が必須ですよね。

また、requireはloadと違って、すでにロード済みのモジュールを読み込まないので二重読み込みや実行効率上有利だというのも分かります。では、逆にloadを使うべきときはいつなのでしょうか?

回答

「loadを使うべき」というよりは「loadでないといけない」場面ですよね。
既にhsbtさんが回答しておられるような場合もそうですし、knsmrさん自身が書いておられるように「requireはloadと違って、すでにロード済みのモジュールを読み込まないので」どうしても二重読みさせたい場合に必要になります。
例えばRailsではdevelopment環境ではapp以下(だけじゃないかも)のスクリプトが更新されていれば再読み込みしますが、これを実現するにはrequireでなくloadが必要になります。

編集 履歴 (1)
  • そういえば、再起動なしにRailsは変更が反映されるのでした。なるほど、今度 Rails を load で grep してみます。ありがとうございました! -
  • Railsのようなことをしたければrequireでなくloadにしないといけない、ということであって、Railsがloadを使っている、という意味ではありません。
    Rails自体は実際にはうんざりするほど複雑なことをしています :)
    -
  • ActiveSupport の dependencies.rb で定義されている require_or_load メソッドが、その名の通り、環境により require したり load したりしています。同ファイルの load? メソッド、railties の bootstrap.rb の :initialize_dependency_mechanism の辺りもご覧ください。 -

rspec.rake のような拡張子が rb, so 以外のファイルを読み込むときに使ってます。

以下のように、拡張子が.txtのようなファイルは load でないと読み込めません。

$ cat hello.txt
puts "hello"

$ irb
> require './hello.txt'
LoadError: cannot load such file -- ./hello.txt
        from /Users/ken/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /Users/ken/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from (irb):3
        from /Users/ken/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'
> load './hello.txt'
hello
 => true
>
編集 履歴 (1)
  • なるほど、require './rspec.rake' とか、require './list.txt' だとエラーになるのですね、気付いていませんでした。 -
  • require と load の違いが分かる実行例を追記しました -

二重読みさせたいケースですと。

起動中のirbでデバッグなどしていて、デバッグ対象のソースコードを修正したあとに修正内容を適用したい!

という場合にloadを使います。逆に私はそれ以外のシーンでは使ったことないですね。

編集 履歴 (0)
  • なるほど! -

最近流行の「設定ファイルを記述する内部DSLとしてRubyを使う」という場面では、そのファイルの読み込みにloadが適切だと思います。

  • 中身がRubyでも拡張子が.rb以外の場合がある(既出のお話)
  • グローバルなデフォルトの設定ととユーザーローカル・プロジェクトローカルなど、複数のファイルを読み込んでローカリティの高いものを優先させる=設定を上書きする必要がある

という理由からです。

編集 履歴 (0)
  • なるほど、2つ目のアプローチは新鮮でした。賢い! -

load の第二引数を利用したいときにも利用します.

るりまから引用します.
http://rurema.clear-code.com/1.9.3/method/Kernel/m/load.html

load(file, priv = false) -> true 
(中略)
[PARAM] priv: 
真のとき、ロード・実行は内部的に生成される無名モジュールをトップレベルとして行われ、グローバルな名前空間を汚染しません。 
(後略)
編集 履歴 (0)
ウォッチ

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