我正在尝试实现一个ActionMailer函数,该函数将向特定用户发送新闻通讯。我想确保时事通讯仅发送给订阅用户。我尝试像这样实现它:
class UserMailer < ActionMailer::Base
def newsletter(user)
return unless user.subscribed # This still renders my mailer view
mail(:to => user.email, :subject => "Newsletter")
end
end
问题是return unless user.subscribed
行似乎仍在呈现邮件程序视图,并且仍然由调用代码(来自 cron 作业)发送:
task :cron => :environment do
User.where(:subscribed => true).each do |user|
UserMailer.newsletter(user).deliver
end
end
请注意,出于性能原因,我的 cron 作业中也有该订阅逻辑(不必迭代所有用户,只需迭代订阅的用户)。但是,感觉 UserMailer 类是此逻辑存在的正确位置(否则调用 newsletter
方法的任何其他位置也需要检查 subscribed
标志。
恕我直言,邮件是这个逻辑的错误地方。邮件发送者除了格式化和发送消息外什么都不做。决定是否发送的逻辑应该在代码的调用块内。这不是正确的方法,而是像以下简单这样简单的事情:
UserMailer.newsletter(user).deliver if user.subscribed?
或者,正如您提到的,您不必遍历所有用户,只需迭代订阅的用户。因此,在User
模型中有一个scope
称为 subscribed
:
User.subscribed.each do |user|
UserMailer.newsletter(user).deliver
end
这样,您就不需要基于每个用户进行测试;仅包含订阅的用户,并且逻辑在调用块中,而不是在邮件程序中。