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

Same problem but in an engine w/ namespaces. No issues in production or in development until a code-change / autoload.

The solution was to

  1. checking for double definitions (there were none)
  2. checking if the module nesting strictly follows rails conventions in the filesystem.

I've had myns under myengine/app/myns/subns/obj.rb but myns is being ignored as it is at the root of the app folder, so moving the myns folder into a subfolder myengine/app/lib/myns solved the issue.

Note: the rails error message was very explicit about the module nesting (while still pointing to the wrong .rb file in the filesystem) so look closely at the error. The error was 'Unable to autoload constant subns/obj.rb in .../myns/subns/obj.rb'. Rails suggesting the incorrect file-location (which exists) is misleading in this case.


You don't need include app/models/concerns and app/controllers/concerns in your autoload/ eagerload paths as they are included by default in Rails 4: https://signalvnoise.com/posts/3372-put-chubby-models-on-a-diet-with-concerns

Also make sure that your concerns are defined as modules, extend ActiveSupport::Concern and with the appropriate file name

#taggable.rb
module Taggable
  extend ActiveSupport::Concern
end

Another cause of your problem might be that some modules/ classes in app/decorators/concerns, lib, lib/shared are using the User class which is not loaded yet or some of it's dependencies are not loaded so try adding require_relative path_to_user.rb at the top of those files

-----Edit-------

Try adding at the top of lib/auth/user_proxy.rb

require_dependency 'app/models/user'

This way you'll remove any ambiguity in autoloading the User class and you won't mess around with Rails autoloading see more here: http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#require-dependency , http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#common-gotchas


1 See if you have any multiple-level class or module declaration done one one line and change them to be declared in several lines.

Instead of

class Parent::Sub::Child
end

Do

module Parent
  module Sub
    class Child
    end
  end
end

2 Check your model association definitions, and ensure you are never using constant. Use string instead.

Instead of

belongs_to :manager, class_name: User

Do

belongs_to :manager, class_name: 'User'

3 Just saw your edit. Can you refactor like this?

# I assume `type` is a string or such, so we can compare classes
# names instead of constants, and get rid of `safe_constantize`
def self.usertype_allowed?(type)
  ['User', 'TempCustomer'].include? type.classify rescue false
end

4 Not a good idea to serialize an active record object in the Thread storage. Change it to store the user id instead, like this:

def set_current_user
  User.current = current_user.id
end

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

def self.current=(user_id)
  Thread.current['current_user_id'] = user_id
end