🦿

【Rails】Zeitwerkについて調べたこと

2021/07/10に公開

Rails6から導入されたZeitwerkとはなんだろう
普段何気なく目にするけどよくわからない。。ということで改めて調べてみて知ったことを自分用にまとめた記事になります。

なぜRailsではrequireなしにファイルを読み込んでくれるのか

他の言語などにおいて、他のファイルを読み込むとなればimportするなどして、明示的に読み込む必要があるはずですが、Railsではそれをよしなにやってくれます。

Railsガイドによるとこう書かれています。

通常のRailsアプリケーションでrequire呼び出しを行うのは、libディレクトリにあるものや、Ruby標準ライブラリ、Ruby gemなどを読み込むときだけです。アプリケーションのクラスやモジュールはどこででも利用できます。

https://railsguides.jp/autoloading_and_reloading_constants.html

なぜでしょうか?
ひとことで言うならZeitwerkという仕組みがRailsには組み込まれているからなのです。

Zeitwerkとは

オートロードの仕組みです。

https://github.com/fxn/zeitwerk

オートロードとは、命名規則にのっとったファイルを自動で読み込むという意味だそうです。

例えば、下記のように(A)のファイル名にもとづいて(B)の定数を読み込もうとする一方で、(B)の定数がどこかで使用されたときには(A)のファイルを読み込もうとするみたいなことを自動でやってくれています。

(A)app/controller/admins/items_controller.rb -> (B)Admins::ItemsController

もしもファイル名と異なる命名規則のモジュール名, クラス名が定義されていた場合はuninitialized constantエラーなど発生し、うまく読み込まれずにエラーになり死んでしまいます。

オートロードが見ているパスの確認方法

じゃあ、Zeitwerkは今どのファイルを自動で読み込んでくれているか?
Railsでは便利な確認方法があり、次のコマンドをたたくと簡単に確認することができます。

$ rails r 'puts ActiveSupport::Dependencies.autoload_paths'
Running via Spring preloader in process 18451
/Users/murakami/HOGE/lib
/Users/murakami/HOGE/app/channels
/Users/murakami/HOGE/app/commands
/Users/murakami/HOGE/app/controllers
/Users/murakami/HOGE/app/errors
/Users/murakami/HOGE/app/forms
...

これでZeitwerkが自動で読み込みしてくれているパスの一覧が出力されて、Zeitwekがきちんと動いていることを確認することができます。

Zeitwekの設定方法

Rails6からは、下記のように記載があるだけで、デフォルトでZeitwerkを使用する設定になっています。

(config/application.rb)
config.load_defaults 6.0

以前のconst_missingを使用するには下記のように設定する必要があるようです。

(config/application.rb)
config.load_defaults 6.0
config.autoloader = :classic # クラシックモードを明示的に指定する

定数の推測をカスタマイズしたくなったら

ファイル名はapp/controllers/api_controller.rbだけど、クラス名はAPIController(APIを全て大文字)で意地でも定義したい! みたいなときもあると思います。

そんなときは下記ファイルに設定してやれば解決できます。

(config/initializers/zeitwerk.rb)
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym "API"
end

他にもファイル名と異なるクラス名, モジュール名を設定したりできるみたいです。
下記の記事がたいへん参考になりました。

https://qiita.com/fursich/items/717a720d9f4465e4cbbb#問題になるケース

おわり

以前使用されていたconst_missingの仕組みを使用したオートロードの仕組みには、
処理順序により発生する不具合があったりして、直感的にエラーに気づきにくいということがあったということらしいですが、このへんの不便さというものを実感せずにここまできていたため「うわーめっちゃ便利になった!」という感覚はないのですが、そのような改善があったのだなーということはなんとなく覚えておこうと思いました。

Discussion