Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

ruby - Rails 6: Zeitwerk::NameError doesn't load class from module

I have a file which looks like this

#app/services/account/authenticate/base.rb
module Account
  module Authenticate
    AuthenticateError = Class.new(StandardError)

    class Base < ::Account::Base
      def self.call(*attrs)
        raise NotImplementedError
      end
    end
  end
end

Now when I will run the code from rails c I have an error

> ::Account::Authenticate::AuthenticateError
=> NameError (uninitialized constant Account::Authenticate::AuthenticateError)
> ::Account::Authenticate.constants
=> [:Base, :ViaToken]

So rails doesn't see AuthenticateError class. But when I will create a nested class from this folder like

=> Account::Authenticate::ViaToken
> ::Account::Authenticate.constants
=> [:Base, :AuthenticateError, :ViaToken]

AuthenticateError class is now visible

> ::Account::Authenticate::AuthenticateError
=> Account::Authenticate::AuthenticateError

The solution for this problem is to create a separate file authenticate_error.rb which will work from the beginning but this solution is not ideal for me. Is there any solution to preload all classes or smth?

(Ruby 2.6 with Rails 6.0.0.rc2)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I experienced this same issue when deploying a Rails 6.0.2 application to an Ubuntu 18.04 server.

Unable to load application: Zeitwerk::NameError: expected file /home/deploy/myapp/app/models/concerns/designation.rb to define constant Designation, but didn't

I found out that the issue was with zeitwerk. Zeitwerk is the new code loader engine used in Rails 6. It’s meant to be the new default for all Rails 6+ projects replacing the old classic engine. Zeitwerk provides the features of code autoloading, eager loading, and reloading.

Here's how I solved it:

Navigate to the config/application.rb file on your project.

Add this line within your application module to switch to classic mode for autoloading:

config.autoloader = :classic

Here's an example:

module MyApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.

    config.autoloader = :classic
  end
end

You can read up more on zeitwerk in this article: Understanding Zeitwerk in Rails 6

That's all.

I hope this helps


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...