LoginSignup
1
3

More than 5 years have passed since last update.

Railsのauto_loadの仕組み

Last updated at Posted at 2017-03-12

[注意]この記事はRails 4.2.6について書かれている。Rails 5では大きく変わっている。

今、とあるRails 4プロジェクトでproductionでも

config.cache_classes = false

にして運用している。つまりdevelopmentと同様に、ソースファイルに変更を加えると、次回のリクエストのときに自動的に再読込される。

もちろん最初はパフォーマンス低下を心配したが、測定してみると数ミリ秒の差もなかったのでこれで数ヶ月運用を続けている。

今回ふと思い立って、このオートロードの仕組みを調べてみた。

基本的にはRailsじゃなくてもActiveSupportの自動require機能を使う - 昼メシ物語にも書かれているように、const_missingをフックしてファイルを読み込んでいる。

しかし、2回目以降のリクエストの場合はすでにクラスが定義されていてconst_missingは発生しないはずである。そこはどうやっているのだろうか?

結論から言うと、オートロードで読み込んだファイルのリストを記録しておき、リクエストのときにそのいずれかに変更があればremove_unloadable_constants!で定数定義を削除している。それによってconst_missingが発生するようになる。

またconfig.cache_classes = falseの場合はActiveSupport::Dependencies.mechanism == :loadになり、requireでなくloadでファイル読み込みをするようになる。

[41] pry(main)> ActiveSupport::Dependencies.mechanism
=> :load

呼び出し関係はこのようになる:

ActionDispatch::Reloader(Rack ミドルウェア)
    ActiveSupport::FileUpdateChecker#execute
        ActiveSupport::Dependencies.clear
            ActiveSupport::Dependencies.remove_unloadable_constants!

以上の理解が正しければ、

  • リクエストがあったときにオートロード対象のいずれかのファイルに変更があれば、それら全てがクリアされる。したがって、const_missingが発生し、遅延が生じる可能性がある(以降のリクエストも含めて)。
  • どのファイルにも変更がなければ、ファイルのタイムスタンプをチェックするだけなので、ほぼ遅延は生じない。

実験してみたらその通りになった。

参考

Rails autoloading — how it works, and when it doesn't
auto_loadは便利さと引き換えに複雑さとトラブルをもたらすという話

Tracing the Rails Autoloader
log_activityなどauto_loadのデバッグに便利なあれこれ

[1] pry(main)> ActiveSupport::Dependencies.log_activity = true
[2] pry(main)> ActiveSupport::Dependencies.logger = Logger.new(STDOUT)
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3