rails-mailerslisted
Install: claude install-skill mickzijdel/rails-toolkit
# Rails Mailers
## Pattern 1: Shallow Mailers, `deliver_later` from a Commit Hook
Mailers stay thin — they just render and pass data. The decision to send lives on the model, triggered `after_create_commit`/`after_update_commit` so the email never fires for a record that then rolls back:
```ruby
# app/models/invitation.rb
class Invitation < ApplicationRecord
after_create_commit :deliver_later
def deliver_later
InvitationMailer.invite(self).deliver_later
end
end
```
```ruby
# app/mailers/invitation_mailer.rb
class InvitationMailer < ApplicationMailer
def invite(invitation)
@invitation = invitation
mail to: invitation.email_address, subject: t(".subject", account: invitation.account.name)
end
end
```
`deliver_later` is the default everywhere — it enqueues an `ActionMailer::MailDeliveryJob` (or your custom `delivery_job`, see Pattern 6) instead of opening an SMTP connection on the request thread. Reach for `deliver_now` only in a Rake task, console, or a job that's already async.
---
## Pattern 2: Multipart Templates + Layout
Ship both an HTML and a text version — some clients/spam filters still expect it, and the text part is the natural degrade for widgets that don't render HTML:
```
app/views/layouts/mailer.html.erb
app/views/layouts/mailer.text.erb
app/views/invitation_mailer/invite.html.erb
app/views/invitation_mailer/invite.text.erb
```
`mail to:` renders both templates automatically when both files exist; no `format.html { ... }` block nee