🦿

【Rails】Zeitwerkとの歩き方

2 min read

Rails6から導入されたというZeitwerkとは何か
普段何気なく使っているこいつ何者! ということで読み方さえわからなかったので、改めて調べてみて知ったことを簡潔にまとめました。(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の仕組みを使用したオートロードの仕組みには、
処理順序により発生する不具合があったりして、直感的にエラーに気づきにくいということがあったということらしいですが、このへんの不便さというものを実感せずにここまで歩んできたため「うわーめっちゃ便利になったやーん」という感動は味わえていないですが、そのような改善に感謝して開発に取り組みたいものです。