I am migrating an ancient app from Rails 5.2 to Rails 6.1 (preparatory to migrating it to 7). I have got the old project structure with a directory called decorators
containing files extending models that have grown very fat (via ModelName.class_eval do...
). In order to keep the structure working I have had to add some lines to application.rb:
module MyApp
class Application < Rails::Application
config.load_defaults 6.1 # do not delete this line
# Don't eager load / autoload the decorators. They don't define classes but extend some.
decorator_dir = "#{Rails.root}/app/decorators"
Rails.autoloaders.main.ignore(decorator_dir)
config.to_prepare do
Dir.glob("#{decorator_dir}/**/*_decorator.rb").sort.each do |override|
load override
end
end
...
When I delete the line config.load_defaults 6.1
the application does not start up any more. It complains undefined method 'ignore' for nil:NilClass
. I have had a look at a new_framework_defaults_6_1.rb file, and it doesn't contain any mention of Rails.autoloaders.
I'd like to understand what is happening here. Can anybody help me?
The exception is saying that Rails.autoloaders.main
is returning nil
. You can use this to see where that method is defined:
Rails.autoloaders.method(:main).source_location
The code is here and it does this:
def main
if zeitwerk_enabled?
@main ||= Zeitwerk::Loader.new.tap do |loader|
loader.tag = "rails.main"
loader.inflector = ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector
end
end
end
When you use config.load_defaults 6.1
that loads the Rails 6.1 defaults here. One thing that happens there is that the autoloader is set to :zeitwerk
:
self.autoloader = :zeitwerk if %w[ruby truffleruby].include?(RUBY_ENGINE)
Rails.autoloaders.main
only returns something if :zeitwerk
is enabled and it's only enabled for you when you are using the 6.1 defaults. :zeitwerk
was also the default in Rails 6.0 for ruby
.
I would recommend upgrading from 5.2 to 6.0 first and work through the Upgrading from Rails 5.2 to Rails 6.0 documentation before you move on to Rails 6.1. This section has more info on the autoloading changes. And this explains how to migrate from Classic to Zeitwerk.