Search code examples
ruby-on-railsrubyrubygemsruby-on-rails-7zeitwerk

Rails 7 error during application start - Zeitwerk-related errors


I'm upgrading my rails app from 6.1 to 7.0 and i'm running into this runtime error:

I do use the Authlogic gem, but the odd thing is i have no config/initializers file for Authlogic, and i can't find any instance of the constant that it's failing on.

uninitialized constant Patches::AuthlogicPasswordPatch (NameError)
  /myapproot/shared/bundle/ruby/3.3.0/gems/zeitwerk-2.6.16/lib/zeitwerk/cref.rb:91:in `const_get'
  /myapproot/shared/bundle/ruby/3.3.0/gems/zeitwerk-2.6.16/lib/zeitwerk/cref.rb:91:in get

UPDATE: After resolving the above issue (see the comment from @alex below for the solution), the next related Zeitwerk issue is:

the next blocker is that Zeitwerk isn't similarly named classes even though they are in different namespaces, which causes this error:

Exception Zeitwerk::NameError in Rack application object 
(expected file app/services/data_tables/base.rb to define 
constant Base, but didn't)

when i enabled logging for Zeitwerk and start the app, i see this:

[email protected]: file app/services/deployment/models/base.rb is ignored because app/services/data_tables/base.rb has precedence

app/services/deployment/models/base.rb is defined as:

module Deployment
  module Models
    class Base < ActiveResource::Base
   ...

and app/services/data_tables/base.rb is:

module DataTables
  class Base
  ...

his is what i have in the config/application.rb:

config.autoload_paths += Dir["#{config.root}/app/services/**/"]
config.eager_load_paths << "#{Rails.root}/lib"
config.eager_load_paths << "#{Rails.root}/app/services"

Solution

  • Adding a summary of fixes done here in case it helps others. Thanks to @XavierNoria and @Alex for their help.

    The initial cause was an outdated patch file for Authlogic that was named in a way that Zeitwerk did not like. I ended up refactoring the code to get rid of the file entirely, but if you have files in lib/patches then you will need to enclose the code inside a Module Patches namespace.

    The other issue was that there were a number of classes where Zeitwerk was refusing to autoload classes that were named the same (even though they were clearly inside different namespaces / folder structures). The fix here was to replace this pre-rails-7.0 line in config/application.rb:

    config.autoload_paths += Dir["#{config.root}/app/services/**/"]
    

    with:

    config.autoload_paths += Dir["#{config.root}/app/services"]
    

    This resolved all the class-name collission issues.