devise_for triggers premature load of Rails components during route drawing in production rake tasks
Summary
When running rake tasks with RAILS_ENV=production, devise_for triggers premature
loading of Rails components during route drawing, causing warnings introduced by a
recent Rails edge change that detects components loaded before application initialization.
Environment
- Rails: edge (main branch), confirmed on 2460b23b38ad
- Devise: 5.0.4
Steps to reproduce
rails new myapp --main
cd myappAdd to Gemfile:
gem "devise"bundle install
bin/rails generate devise:install
bin/rails generate devise Administrator
RAILS_ENV=production bin/rails db:prepareExpected behavior
Completes without any warnings.
Actual behavior
The following warning is printed:
:active_model_secure_password was loaded before application initialization.
Prematurely executing load hooks will slow down your boot time
and could cause conflicts with the load order of your application.
Please wrap your code with an on_load hook:
ActiveSupport.on_load(:active_model_secure_password) do
# your code here
end
Called from:
...
/devise/mapping.rb ...
/config/routes.rb ...Estimated cause
Rails edge introduced a load hook guard mechanism (rails/rails#56201) that warns when Rails components are loaded before the application is fully initialized.
When RAILS_ENV=production, routes are eager-loaded. devise_for :administrators
causes the Administrator model to be loaded via constantize during route drawing,
in order to determine which Devise modules are included (e.g. :registerable) and
thus which routes to generate. This triggers the new Rails warning as
ActiveModel::SecurePassword (and other components) are loaded before the
application is fully initialized.
This only reproduces under RAILS_ENV=production with a Rake task because
config.rake_eager_load defaults to false, overriding config.eager_load = true
at Rake task execution time — making the Rails load hook guard condition
(!Rails.configuration.eager_load) pass.
Source: heartcombo/devise