Skip to content

Defer mailer include via ActiveSupport.on_load(:action_mailer)#926

Merged
scambra merged 1 commit into
scambra:masterfrom
benaitcheson:defer-mailer-include-via-on-load
May 22, 2026
Merged

Defer mailer include via ActiveSupport.on_load(:action_mailer)#926
scambra merged 1 commit into
scambra:masterfrom
benaitcheson:defer-mailer-include-via-on-load

Conversation

@benaitcheson
Copy link
Copy Markdown
Contributor

Fixes #925.

config.to_prepare in the Engine forces Devise.mailer to constantize during the Rails finisher initializer, which in turn loads ActionMailer::Base (and, via MailDeliveryJob, ActiveJob::Base) before Rails.application.initialized? flips. Rails edge's new guard_load_hooks support (rails/rails#56201) reports this as a premature load-hook for both :action_mailer and :active_job on every boot.

This change wraps the body of the to_prepare block in ActiveSupport.on_load(:action_mailer):

  • First boot. to_prepare registers an on_load(:action_mailer) hook. Nothing loads ActionMailer::Base yet. When something later resolves a mailer (sending an invitation, etc.), the hook fires and the include runs against the loaded mailer class. App init has already completed, so no warning.
  • Subsequent to_prepare cycles (dev reloads). :action_mailer has already fired, so the freshly-registered on_load block runs immediately, re-applying the include on the reloaded Devise.mailer class — same behaviour as before.

No functional change for stable Rails users; just silences the boot warnings on Rails edge and saves a small amount of boot time by deferring the mailer load.

I didn't add a regression test — wasn't sure how to best exercise railtie load order in the existing harness. Happy to add one if you'd like, or to take suggestions on the right approach.

The to_prepare callback was forcing Devise.mailer (a String#constantize)
to resolve at app initialization time, which loaded ActionMailer::Base
and — via the default ActionMailer::Base inheritance chain pulling in
MailDeliveryJob — ActiveJob::Base before app initialization completed.

Rails edge's guard_load_hooks support (rails/rails#56201) reports both
loads as 'loaded before application initialization' on every boot.

Wrapping the include in on_load(:action_mailer) keeps the include
happening on every reload (the on_load callback runs immediately when
re-registered after :action_mailer has fired) without forcing the load
during the Rails finisher initializer.
@scambra scambra merged commit fbb3174 into scambra:master May 22, 2026
27 of 55 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rails edge: premature :action_mailer / :active_job load-hook warnings on every boot

2 participants