Search code examples
ruby-on-railszeitwerk

Undefined constant errors after Rails 7 upgrade with class names containing part of modules


After upgrading my gem to Rails 7, I am seeing a lot of undefined constants errors.

For example:

app/models/my_gem/api/irr_item.rb

module MyGem
  module Api
    class IrrItem < MyGem::Api::ApplicationRecord

When making IRR uppercase in my class, it fixes the issue:

module MyGem
  module Api
    class IRRItem < MyGem::Api::ApplicationRecord

Or another situation:

app/constraints/graphiql_route_constraint.rb

class GraphiqlRouteConstraint

When making QL uppercase in my class, it fixes the issue:

class GraphiQLRouteConstraint

I fixed all my issues by uppercasing these but I don't understand why. Is it because I have a module called IRR somewhere and now it needs to be uppercase all the time?


Solution

  • In classic, the input of the autoloader was the name of the missing constant, "IrrItem". The autoloader underscored it, "irr_item", and looked up the file in the file system.

    Zeitwerk works the other way around. The input of the autoloader is the file name, and assumes "irr_item".camelize is the constant defined there. As @max said, looks like the application has acronyms defined.

    I guess it would be nice that the acronyms are used across all their instances. But to unblock this quickly you could hard-code inflections for these special cases:

    # config/initializers/zeitwerk.rb
    
    # IRR and GraphQL are defined as acronyms, but we have
    # some classes whose names do not take them into account.
    # If they get ever renamed, please remove this configuration.
    
    main = Rails.autoloaders.main
    main.inflector.inflect(
      "irr_item" => "IrrItem",
      "graphiql_route_constraint" => "GraphiqlRouteConstraint"
    )
    

    Please check out these docs for further details.

    See also the guide Classic to Zeitwerk HOWTO for more stuff that may show up in the migration.