Railsの開発環境の自動再読み込みはどうやってるのか

以前から気になっていたけど調べたことのなかったRailsのアノ機能を調べてみました。開発環境でソースを修正→ブラウザーをリロード→変更が反映、の機能です。

どうやっているかというと、RubyのModule#const_missingとModule#remove_constを使っています。ソースコードactivesupport-x.x.x/lib/active_support/dependencies.rbにあります。

  1. Module#const_missingを定義する。
    1. 存在しないクラス名(定数名)にぶつかると、const_missingが呼ばれる。
    2. const_missingでは、クラス名をファイル名に変換し、ディレクトリ(app/controllers、app/models、libなど)を調べて、ファイルがあればrequireまたはloadする。
    3. 新しいクラス名が定義されれば、名前を保存しておく。
  2. リロードされたら(HTTPリクエストが来たら)、保存したクラス名(定数名)をすべてModule#remove_constで削除する。
    1. 1-1.に戻る。

ソースファイルのタイムスタンプを見ているかと思ってましたが、そこまではしていないようです。

リロードするたびにクラスオブジェクトがメモリに溜まっていきそうな感じですが、そこはRubyガベージコレクションで適宜開放されるのでしょう。

次のコードをenvironment.rbに追加すると、dependencies.rbでクラスが読み込まれたり、削除されたりするのをコマンドプロンプトで観察できます。

ActiveSupport::Dependencies.logger = Rails.logger
ActiveSupport::Dependencies.log_activity = true

Rails以外のプログラムでも、ActiveSupportを使うか、dependencies.rbのような機能を自作すれば、「クラス名に対応するソースを自動的に読み込み」ができるでしょう。