We're upgrading our app from Ruby 2.7 to 3.0 and Rails 5.2 to 6.0 at the same time (I started with just Ruby but 3.0 doesn't seem to be compatible with 5.2). It's close but getting an odd error: uninitialized constant UserFields::Boolean (NameError)
on start up when we have our user model's fields split off into a concern:
class User
include Mongoid::Document
include Mongoid::Timestamps
#field :force_password_change, type: Boolean, default: false
include UserFields
....
end
module UserFields
extend ActiveSupport::Concern
included do
## Database authenticatable
field :email, :type => String, :default => ""
field :force_password_change, type: Boolean, default: false ### <<<< ERROR HERE
end
end
If I put the Boolean fields directly in the model, it works fine but not when they are in the concern. The error trace:
! Unable to load application: NameError: uninitialized constant UserFields::Boolean
2024-01-10 15:22:22 bundler: failed to load command: puma (/app/bundle_cache/ruby/3.0.0/bin/puma)
2024-01-10 15:22:22 /app/app/models/concerns/user_fields.rb:8:in `block in <module:UserFields>': uninitialized constant UserFields::Boolean (NameError)
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/concern.rb:122:in `class_eval'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/concern.rb:122:in `append_features'
2024-01-10 15:22:22 from /app/app/models/user.rb:9:in `include'
2024-01-10 15:22:22 from /app/app/models/user.rb:9:in `<class:User>'
2024-01-10 15:22:22 from /app/app/models/user.rb:4:in `<main>'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/bootsnap-1.17.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/bootsnap-1.17.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/zeitwerk-2.6.12/lib/zeitwerk/kernel.rb:30:in `require'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/inflector/methods.rb:282:in `const_get'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/inflector/methods.rb:282:in `block in constantize'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/inflector/methods.rb:280:in `each'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/inflector/methods.rb:280:in `inject'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/inflector/methods.rb:280:in `constantize'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/activesupport-6.0.6.1/lib/active_support/dependencies/zeitwerk_integration.rb:19:in `constantize'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise.rb:325:in `get'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/mapping.rb:83:in `to'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/mapping.rb:78:in `modules'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/mapping.rb:95:in `routes'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/mapping.rb:162:in `default_used_route'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/mapping.rb:72:in `initialize'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise.rb:361:in `new'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise.rb:361:in `add_mapping'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/rails/routes.rb:243:in `block in devise_for'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/rails/routes.rb:242:in `each'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/devise-4.9.3/lib/devise/rails/routes.rb:242:in `devise_for'
2024-01-10 15:22:22 from /app/config/routes.rb:264:in `block in <main>'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/actionpack-6.0.6.1/lib/action_dispatch/routing/route_set.rb:426:in `instance_exec'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/actionpack-6.0.6.1/lib/action_dispatch/routing/route_set.rb:426:in `eval_block'
2024-01-10 15:22:22 from /app/bundle_cache/ruby/3.0.0/gems/actionpack-6.0.6.1/lib/action_dispatch/routing/route_set.rb:408:in `draw'
2024-01-10 15:22:22 from /app/config/routes.rb:1:in `<main>'
It stems from the routes file since we use Devise and that is using the User model. I'm sure it has to do with the upgrade as the same code has worked for years in 5.2/2.7. Any help is appreciated.
Update: It is likely this has to do with an upgrade to your mongoid
gem. I am not certain what version you were previously using but it appears that < 7.3 defined the top level constant ::Boolean
which would allow this to resolve appropriately if you just wrote Boolean
Source. Newer versions do not include this top level constant.
Release Notes state:
::Boolean
Removed...code that is not executed in the context of a class including Mongoid::Document may need to explicitly qualify Boolean references.
...Additionally, in Mongoid 7.2
::Boolean
andMongoid::Boolean
were different classes. In Mongoid 7.3 there is only one class which isMongoid::Boolean
.
Since your concern is evaluated outside of the context of the class that includes Mongoid::Document
you will need to explicitly qualify the constant as Mongoid::Boolean
.
e.g.
module UserFields
extend ActiveSupport::Concern
included do
## Database authenticatable
field :email, type: String, default: ""
field :force_password_change, type: Mongoid::Boolean, default: false
end
end