Search code examples
ruby-on-railsruby-on-rails-4eager-loading

"Unable to autoload constant User" error when changed code in development


I have a problem with my rails application. After an Update from Rails 3 to 4. When I surf through the pages after starting the server in development mode everything is fine.

But after a single code change (even adding a space) every page request shows the following error.

Unable to autoload constant User, expected /path/to/my/rails-app/app/models/user.rb to define it

The file lives exactly there and defines the class:

class User < ActiveRecord::Base
  …

I tried many things with config.autoload_paths and config.eager_load_paths in application.rb but with no luck. Deactivating spring did not help either.

Developing an app and having to restart the server after every single change seems so 90s.

$ rails -v
Rails 4.2.4
$ ruby -v
ruby 2.1.7p400 (2015-08-18 revision 51632) [x86_64-linux]

Some relevant configs:

development.rb

MyApp::Application.configure do
    # Settings specified here will take precedence over those in config/application.rb

  # In the development environment your application's code is reloaded on
  # every request.  This slows down response time but is perfect for development
  # since you don't have to restart the webserver when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot. This avoids loading your whole application
  # just for the purpose of running a single test. If you are using a tool that
  # preloads Rails for running tests, you may have to set it to true.
  config.eager_load = false

  # Show full error reports and disable caching
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false

  # Don't care if the mailer can't send
  config.action_mailer.raise_delivery_errors = false

  # Print deprecation notices to the Rails logger
  config.active_support.deprecation = :log

  # Only use best-standards-support built into browsers
  config.action_dispatch.best_standards_support = :builtin

  # Do not compress assets
  config.assets.compress = false

  # Expands the lines which load the assets
  config.assets.debug = true

  config.action_mailer.delivery_method = :test
  config.action_mailer.default_url_options = {
    host: 'localhost',
    port: 3000
  }

end

application.rb

module Serviceportal
  class Application < Rails::Application    
    # Enable the asset pipeline
    config.assets.enabled = true

    # Version of your assets, change this if you want to expire all your assets
    config.assets.version = '1.0'

    [… some asset precompile stuff …]

    # Configure the default encoding used in templates for Ruby 1.9.
    config.encoding = 'utf-8'

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += Dir["#{config.root}/app/mailers",
        "#{config.root}/app/controllers/concerns",
        "#{config.root}/app/models/concerns",
        "#{config.root}/app/decorators/concerns",
        "#{config.root}/lib",
        "#{config.root}/lib/shared"
    ]
    config.eager_load_paths += Dir["#{config.root}/app/mailers",
        "#{config.root}/app/controllers/concerns",
        "#{config.root}/app/models/concerns",
        "#{config.root}/app/decorators/concerns",
        "#{config.root}/lib",
        "#{config.root}/lib/shared"]

    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
    config.time_zone = 'Berlin'

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    config.i18n.default_locale = :de

    [… some SQL and active support stuff …]

    config.action_controller.include_all_helpers = false

    config.action_controller.action_on_unpermitted_parameters = :raise

    # Do not swallow errors in after_commit/after_rollback callbacks.
    config.active_record.raise_in_transactional_callbacks = true
  end
end

Edit: The error mostly shows up in lib/auth/user_proxy.rb in the following function. Maybe this helps to narrow the range of possible causes.

def self.usertype_allowed?(type)
  [ User, TempCustomer ].include? type.classify.safe_constantize rescue false
end

Edit 2: Stringify the class names in Edit 1 helped (thanks @Benjamin Sinclaire). But only leads to the next errors. I could also avoid using classes. But at the following error in app/controllers/concerns/security.rb there is nothing can change?

Unable to autoload constant User, expected /path/to/my/rails-app/app/models/user.rb to define it

code:

def set_current_user
  User.current = current_user
end

with current user saved in the Thread (code from /path/to/my/rails-app/app/models/user.rb

def self.current
  Thread.current['current_user']
end

def self.current=(user)
  Thread.current['current_user'] = user
end

Just to make it clear again: It works after server restart in development until I change some code somewhere.


Solution

  • During a Rails/Ruby Update I found time to look into this and finally found the cause.

    The user class had an unloadable in it for years. That caused the problems since Rails 4. Now I removed this and found no issues after that.