Rails Zeitwerk: auto-load your twerk
The Rails magic pudding, just how do all those Classes, Modules, and helpers come to life ? To be honest when I was at lewagon bootcamp I was just happy that they were there at all, just a rails g scaffold Post name:string title:string content:text and you have the beginnings of your blog in 15 minutes.
Well the magic pudding relies on to start with:
- the rails file naming conventions
- the code auto-loader / eager-loader, that pre
rails 6was classic and is now zeitwerk (more on the differences later).
how to bake me a Class initialized constant ?
zeitwerk starts by playing initalized constants hide and seek. So if we are wanting in instantiate the following model classes inside the rails console:
Namespaced::Authentication
Namespaced::User
Inside a rails app we would want our folder structure to be below:
app/models/namespaced/user.rb
app/models/namespaced/authentication.rb
an example of the authentication.rb file below:
module Namespaced
class Authentication < ApplicationRecord
belongs_to :user, foreign_key: 'namespaced_user_id', inverse_of: :authentications
end
end
Your module and Classnames need to be reflected in the the folder structure in order for the auto-loader to play an effective game of hide & seek with your Classnames and vice versa.
Also when you’re in rails console and you have made changes to Classes or Classnames in your editor to refresh you can:
Loading development environment (Rails 6.0.3)
[1] pry(main)> reload!
Reloading...
=> true
the classic pudding vs. zeitwerk hazelnut slice
The classic pudding uses:
autoload_pathsthenconst_missing
Ruby fires a const_missing callback every time it finds an unknown constant reference during code execution. Ruby’s const_missing callback is overridden by Rails, which normally raises a NameError. In its place, it attempts to load the file associated with the constant being searched for.
The autoload_paths come into play at this point. Rails searches the autoload_paths list looking for the “SnakeCase” version of the referenced constant and loads/requires the file if it exists.
This is great until it’s not..
You can dig into that example here at rails guides
The zeitwerk hazelnut slice gets around this by:
autoload_pathsis still leveraged- then the use of the Ruby native method
Modeule#autoloadfor operation constants hide and seek
In the case of our Namespaced authentication.rb and user.rb app/models from above, Zeitwerk executes the below code in the butlers pantry:
autoload :Authentication, Rails.root.join('app/models/namespaced/authentication.rb')
autoload :User, Rails.root.join('app/models/namespaced/user.rb')
The end result is const_missing from classic is deprecated, & the build in autoload is leveraged.
All this ‘magic’ is still reliant on the file naming conventions withing the rails framework. Don’t do what I do and pluralize your
modelnames and then wonder for 5 minutes why nothing is working..
references: