1

我有一个简单的功能来防止在本地测试时向客户发送电子邮件:

def safe_emails emails
  if Rails.env == 'production'
    emails
  else
    emails.select{|e| ['staff@example.com', 'staff2@example.com'].include?(e) }
  end
end

我想在邮件程序之间共享该功能。我可以看到两个选项,一个模块或一个类方法。

选项 1:模块

class ReportMailer < ActionMailer::Base
  include SafeEmailer

  def daily emails
    mail_to: safe_emails(emails)
  end
end

选项2:类方法

class ReportMailer < ActionMailer::Base
  def daily emails
    mail_to: SafeEmailer.safe_emails(emails)
  end
end

由于全局范围,根据某些人的说法,类方法是禁止的,包括具有一种方法的模块似乎并不那么有吸引力。猴子修补 ActionMailer 以将方法扔在那里似乎也可能导致麻烦(当 Rails 4.3 引入 safe_emails 方法或其他方法时)。

4

3 回答 3

1

这可能是最简单的方法。

在您的非生产环境中设置以下配置。(config/environments/.rb)

config.action_mailer.delivery_method = :smtp (default), :sendmail, :test, or :file

看看开信刀宝石。您可以将 delivery_method 设置为letter_opener并在浏览器中打开电子邮件,而不是在非生产环境中实际发送它们。

于 2013-08-22T21:29:02.073 回答
1

即使它是一个简单的功能模块,我也会选择模块选项。在一个模块中保留一个最终可以被多个类使用的通用函数比在一个类中定义它更有意义。

如果你关心 Rails 4.3,那么你可以简单地用include MySafeEmailModuleRails 4.3 包含这个函数的任何东西替换你,而不是查找和替换所有对ReportMailer.daily_emails.

于 2013-08-22T20:15:17.903 回答
1

两者都不 - 在您的情况下,您需要一个策略对象,它决定谁接收有关Rails.env. 我会将这种逻辑保留在ReportMailer.

我会选择类似的东西:

UserMailer.welcome_email(@user).deliver if SafeEmailer.new(@user.email).safe?
于 2013-08-22T21:00:17.657 回答