published under license CC4-BY
posted in category Software Development & Programming / Ruby on Rails
posted at 01. Apr '22
When to_prepare Hook Is Too Late
When I upgraded to Ruby on Rails 6.1, I had to deal with preload problems:
damon@rapthalia:~/oni_sorceress> bin/rails s
=> Booting Puma
=> Rails 6.1.4.1 application starting in development
=> Run `bin/rails server --help` for more startup options
Exiting
/home/damon/.rbenv/versions/3.0.3/lib64/ruby/gems/3.0.0/gems/actionpack-6.1.4.1/lib/action_dispatch/middleware/stack.rb:144:in `push': can't modify frozen Array: [Webpacker::DevServerProxy, ActionDispatch::HostAuthorization, Rack::Sendfile, ActionDispatch::Static, ActionDispatch::Executor, ActiveSupport::Cache::Strategy::LocalCache::Middleware, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, ActionDispatch::RemoteIp, Sprockets::Rails::QuietAssets, Rails::Rack::Logger, ActionDispatch::ShowExceptions, WebConsole::Middleware, ActionDispatch::DebugExceptions, ActionDispatch::ActionableExceptions, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::Migration::CheckPending, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ContentSecurityPolicy::Middleware, ActionDispatch::PermissionsPolicy::Middleware, Rack::Head, Rack::ConditionalGet, Rack::ETag, Rack::TempfileReaper] (FrozenError)
DEPRECATION WARNING: Initialization autoloaded the constants ApplicationRecord and AnalyticsHttpRequest.
Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.
Reloading does not reboot the application, and therefore code executed during
initialization does not run again. So, if you reload ApplicationRecord, for example,
the expected changes won't be reflected in that stale Class object.
These autoloaded constants have been unloaded.
In order to autoload safely at boot time, please wrap your code in a reloader
callback this way:
Rails.application.reloader.to_prepare do
# Autoload classes and modules needed at boot time here.
end
That block runs when the application boots, and every time there is a reload.
For historical reasons, it may run twice, so it has to be idempotent.
Check the "Autoloading and Reloading Constants" guide to learn more about how
Rails autoloads and reloads.
(called from <top (required)> at /home/damon/oni_sorceress/config/environment.rb:5)
.........
The problem with to_prepare
hook was that it was too late. I got cannot add middleware to a frozen array error.
I won’t lie, it took me months to fix that, main motivation was upgrade to Ruby on Rails 7.
Fortunately there are more hooks - https://guides.rubyonrails.org/configuring.html#initialization-events
and before_initialize
worked just fine. I have to manually load model file which is used by middleware though.
require Rails.root.join('app', 'models', 'application_record').to_s
require Rails.root.join('app', 'models', 'oni_sorceress_record').to_s
require Rails.root.join('app', 'models', 'oni_sorceress', 'analytics').to_s
require Rails.root.join('app', 'models', 'oni_sorceress', 'analytics', 'request').to_s
Rails.configuration.before_initialize do
Rails.application.config.middleware.use(
RackRequestObjectLogger,
::OniSorceress::Analytics::Request
)
end
So…that’s it.
Add Comment