1
0
mirror of https://github.com/jbranchaud/til synced 2026-07-02 15:49:44 +00:00

Add Halt ActionMailer Delivery With Callback as a Rails TIL

This commit is contained in:
jbranchaud
2026-05-23 12:33:02 -05:00
parent 3eddb54053
commit 539cbbefa6
2 changed files with 48 additions and 1 deletions
+2 -1
View File
@@ -10,7 +10,7 @@ working across different projects via [VisualMode](https://www.visualmode.dev/).
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter).
_1795 TILs and counting..._
_1796 TILs and counting..._
See some of the other learning resources I work on:
@@ -1175,6 +1175,7 @@ If you've learned something here, support my efforts writing daily TILs by
- [Get The Column Names For A Model](rails/get-the-column-names-for-a-model.md)
- [Get The Current Time](rails/get-the-current-time.md)
- [Grab A Random Record From The Database](rails/grab-a-random-record-from-the-database.md)
- [Halt ActionMailer Delivery With Callback](rails/halt-action-mailer-delivery-with-callback.md)
- [Handle Named Arguments In A Rake Task](rails/handle-named-arguments-in-a-rake-task.md)
- [Hash Slicing](rails/hash-slicing.md)
- [Ignore Poltergeist JavaScript Errors](rails/ignore-poltergeist-javascript-errors.md)
@@ -0,0 +1,46 @@
# Halt ActionMailer Delivery With Callback
`ActionMailer` supports callbacks, similar to `ActiveRecord`, like
`before_deliver` and `after_delivery`. We can hook into the `before_deliver`
callback to interrupt the delivery of an email that shouldn't go out.
Here's the scenario: you schedule a bunch of payment reminders to go out to your
customers that still need to make their latest payment. Let's say the daily job
that schedules all of these reminders runs in the middle of the night, but
schedules the emails to land in inboxes at a more reasonable time, like 10am.
Between the time that the email is scheduled and it gets processed for delivery,
a customer makes their payment. In that case, we no longer want to send that
person an email reminder.
To handle this scenario, we can have a `before_deliver` callback that checks the
user's balance and raises `:abort` to halt the callback execution chain,
effectively preventing the email from going out. We can even scope the callback
to just the actions we care about using the `if` option and checking the
`action_name`.
```ruby
class UserMailer < ApplicationMailer
before_deliver :abort_if_payment_is_current,
if: -> { action_name.in?(%w[payment_reminder past_due_invoice]) }
def payment_reminder
# ...
end
def past_due_invoice
# ...
end
private
def abort_if_payment_is_current
if @user.check_latest_balance.zero?
raise :abort
end
end
end
```
See [Action Mailer
Callbacks](https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-callbacks)
for more details.