Have you ever encountered a cryptic uninitialized constant issue, where the module name appears duplicated in the error message:

NameError:
       uninitialized constant Education::Engine::Student::Education
       Did you mean?  Education
For some reason, the module (Education) is being appended to the end of the constant. We figured that this was a red-herring that was hiding the root cause.

The other week two colleagues independently encountered "uninitialized constant" errors with the above characteristics, which were simple to fix, but a bit more tricky to diagnose.

We did the thing that most developers do in a problem solving situation and researched the error on Google, but this didn't yield anything useful. This quick write up is an attempt to document what we learned so that anyone else having this issue hopefully wastes less time trying to figure out the problem.

Let's say we have two models that relate to each other. A teacher has many students. A student belongs to a teacher:

module Education::Engine
  class Teacher
    include Mongoid::Document
    include Mongoid::Timestamps

    store_in collection: 'teachers'

    has_many :students, class_name: 'Education::Engine::Student', inverse_of: :teacher

  end
end
module Education::Engine
  class Student
    include Mongoid::Document
    include Mongoid::Timestamps

    store_in collection: 'students'

    belongs_to :teacher, class_name: 'Education::Engine::Teacher', inverse_of: :students

    as_enum :type, full_time: 0, part_time: 1
  end
end
app/models/student.rb

When we came to run our rspec tests we encountered an error message that looked a little bit like this:

NameError:
       uninitialized constant Education::Engine::Student::Education
       Did you mean?  Education

For some reason, the module (Education) is being appended to the end of the constant. We figured that this was a red-herring that was hiding the root cause.

The subtle trick here to make the error message more meaningful is to root the namespace by appending :: to the front of the namespace.

So in our Student model:

belongs_to :teacher, class_name: 'Education::Engine::Teacher', inverse_of: :students

Becomes:

belongs_to :teacher, class_name: '::Education::Engine::Teacher', inverse_of: :students

After this change, we ran the tests again and the error message had changed to:

NoMethodError:
    undefined method `as_enum' for Education::Engine::Student:Class

In our specific situation we were missing an include statement (include SimpleEnum::Mongoid) from our Student model.

Chances are if you see an uninitialized constant error like we have, there is something wrong with your model that is being hidden by Rails trying to be smart with resolving model relationships. Rooting the namespace of the relation classes could help reveal the real error.