Rails 6 comes with Zeitwerk as the new default loader. For most users, when upgrading from the previous version of Rails, not much would change (except some inflections because of the way zeitwerk
infers file names based on the constant).
For people using Single-Table-Inheritance, Rails upgrade guide already provides a drop in script that can be used to eager load STI classes by reading the type column in the DB.
But if you rely on descendants
to find out STI classes (e.g. for displaying a selector on the UI), you will notice that descendants
doesn’t discover all classes during development. One easy workaround is to enable eager_load
directly in config/development.rb
. This works but will slow down the initial start of the project considerably and you will notice that it still doesn’t work with auto-reload. A better way is to use eager_load_paths
combined with ActiveSupport::Reloader
’s to_prepare
hook inside development.rb
.
config.eager_load_paths += Dir["app/models/stimodel/**/*.rb"]
ActiveSupport::Reloader.to_prepare do
Dir["app/models/stimodel/**/*.rb"].each { |f| require_dependency("#{Dir.pwd}/#{f}") }
end
Adding your paths to eager_load_paths
make sure that Rails loads them when it starts up. To make sure that Rails reloads our models if we do any changes or add new files, we also need to hook into the Reloader
’s to_prepare
hook and manually require the dependency there.
Don’t get tripped with the require_dependency
because Rails 6 changelog mentioned that all known use cases of require_dependency
were eliminated. Of course, with the default lazy loading approach that Rails provides, we don’t need require_dependency
in our code anymore. But this is an advanced usage where we are asking it manually to eager load that dependency so it is still required here.