action-mailer-coder
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAction Mailer Coder
Action Mailer 编码指南
Mailer Design Principles
邮件器设计原则
Group Related Emails
归类相关邮件
ruby
class NotificationMailer < ApplicationMailer
def comment_reply(user, comment)
@user = user
@comment = comment
mail(to: @user.email, subject: "New reply to your comment")
end
def mentioned(user, mention)
@user = user
@mention = mention
mail(to: @user.email, subject: "You were mentioned")
end
endruby
class NotificationMailer < ApplicationMailer
def comment_reply(user, comment)
@user = user
@comment = comment
mail(to: @user.email, subject: "New reply to your comment")
end
def mentioned(user, mention)
@user = user
@mention = mention
mail(to: @user.email, subject: "You were mentioned")
end
endParameterized Mailers
参数化邮件器
ruby
class NotificationMailer < ApplicationMailer
before_action { @user = params.fetch(:user) }
before_action { @account = params.fetch(:account) }
def comment_reply
@comment = params.fetch(:comment)
mail(to: @user.email, subject: "New reply on #{@account.name}")
end
endruby
class NotificationMailer < ApplicationMailer
before_action { @user = params.fetch(:user) }
before_action { @account = params.fetch(:account) }
def comment_reply
@comment = params.fetch(:comment)
mail(to: @user.email, subject: "New reply on #{@account.name}")
end
endCalling the mailer
调用邮件器
NotificationMailer.with(user: user, account: account, comment: comment).comment_reply.deliver_later
undefinedNotificationMailer.with(user: user, account: account, comment: comment).comment_reply.deliver_later
undefinedDynamic Defaults with Inheritance
基于继承的动态默认配置
ruby
class AccountMailer < ApplicationMailer
default from: -> { build_from_address }
before_action { @account = params.fetch(:account) }
private
def build_from_address
@account.custom_email_sender? ?
email_address_with_name(@account.custom_email_address, @account.custom_email_name) :
email_address_with_name("hello@example.com", @account.name)
end
endruby
class AccountMailer < ApplicationMailer
default from: -> { build_from_address }
before_action { @account = params.fetch(:account) }
private
def build_from_address
@account.custom_email_sender? ?
email_address_with_name(@account.custom_email_address, @account.custom_email_name) :
email_address_with_name("hello@example.com", @account.name)
end
endBackground Delivery
后台发送
ruby
UserMailer.with(user: user).welcome.deliver_later # Immediate queue
UserMailer.with(user: user).welcome.deliver_later(wait: 1.hour) # Delayed
UserMailer.with(user: user).digest.deliver_later(wait_until: Date.tomorrow.morning) # Scheduledruby
UserMailer.with(user: user).welcome.deliver_later # 立即加入队列
UserMailer.with(user: user).welcome.deliver_later(wait: 1.hour) # 延迟发送
UserMailer.with(user: user).digest.deliver_later(wait_until: Date.tomorrow.morning) # 定时发送Email Previews
邮件预览
ruby
undefinedruby
undefinedtest/mailers/previews/notification_mailer_preview.rb
test/mailers/previews/notification_mailer_preview.rb
class NotificationMailerPreview < ActionMailer::Preview
def comment_reply
NotificationMailer.with(
user: User.first,
account: Account.first,
comment: Comment.first
).comment_reply
end
end
Access at: `http://localhost:3000/rails/mailers`class NotificationMailerPreview < ActionMailer::Preview
def comment_reply
NotificationMailer.with(
user: User.first,
account: Account.first,
comment: Comment.first
).comment_reply
end
end
访问地址:`http://localhost:3000/rails/mailers`Internationalization
国际化
ruby
def welcome
@user = params.fetch(:user)
I18n.with_locale(@user.locale) do
mail(to: @user.email, subject: t(".subject", name: @user.name))
end
endruby
def welcome
@user = params.fetch(:user)
I18n.with_locale(@user.locale) do
mail(to: @user.email, subject: t(".subject", name: @user.name))
end
endAttachments
附件处理
ruby
def invoice(order)
attachments.inline["logo.png"] = File.read("app/assets/images/logo.png")
attachments["invoice.pdf"] = generate_pdf(order)
mail(to: order.email, subject: "Your Invoice ##{order.number}")
endruby
def invoice(order)
attachments.inline["logo.png"] = File.read("app/assets/images/logo.png")
attachments["invoice.pdf"] = generate_pdf(order)
mail(to: order.email, subject: "Your Invoice ##{order.number}")
endTesting (RSpec)
测试(RSpec)
ruby
RSpec.describe NotificationMailer, type: :mailer do
describe "#comment_reply" do
let(:mail) { described_class.with(user: user, comment: comment).comment_reply }
it "renders the headers" do
expect(mail.subject).to match(/New reply/)
expect(mail.to).to eq([user.email])
end
it "delivers later" do
expect { mail.deliver_later }.to have_enqueued_job(ActionMailer::MailDeliveryJob)
end
end
endruby
RSpec.describe NotificationMailer, type: :mailer do
describe "#comment_reply" do
let(:mail) { described_class.with(user: user, comment: comment).comment_reply }
it "renders the headers" do
expect(mail.subject).to match(/New reply/)
expect(mail.to).to eq([user.email])
end
it "delivers later" do
expect { mail.deliver_later }.to have_enqueued_job(ActionMailer::MailDeliveryJob)
end
end
endAnti-Patterns
反模式
| Anti-Pattern | Problem | Solution |
|---|---|---|
| One mailer per email | Hard to navigate | Group related emails |
Skipping | Implicit dependencies | Use parameterized mailers |
| Blocks request | Use |
| Missing previews | Can't visually test | Create preview classes |
| 反模式 | 问题 | 解决方案 |
|---|---|---|
| 每个邮件对应一个邮件器 | 难以导航管理 | 归类相关邮件 |
跳过 | 存在隐式依赖 | 使用参数化邮件器 |
使用 | 阻塞请求 | 使用 |
| 缺少预览类 | 无法进行可视化测试 | 创建预览类 |
Output Format
输出格式
When creating mailers, provide:
- Mailer Class - The complete implementation
- Views - HTML and text templates
- Preview - Preview class for visual testing
- Tests - Example test cases
创建邮件器时,需提供:
- 邮件器类 - 完整的实现代码
- 视图 - HTML和文本模板
- 预览类 - 用于可视化测试的预览类
- 测试用例 - 示例测试代码