#ruby-on-rails #actionmailer
#ruby-on-rails #actionmailer
Вопрос:
Я пытаюсь реализовать функцию 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
флаг.
Ответ №1:
Почтовая программа, ИМХО, не подходит для этой логики. Почтовая программа не должна ничего делать, кроме форматирования и отправки сообщений. Логика для принятия решения о том, отправлять или нет, должна находиться в вызывающем блоке кода. Это неправильный способ, но что-то такое простое, как:
UserMailer.newsletter(user).deliver if user.subscribed?
С другой стороны, как вы упомянули, вам не нужно перебирать всех пользователей, только подписанных. Итак, с scope
в User
модели, вызываемой subscribed
:
User.subscribed.each do |user|
UserMailer.newsletter(user).deliver
end
Таким образом, вам не нужно тестировать для каждого пользователя; включаются только подписанные пользователи, а логика находится в вызывающем блоке, а не в почтовой программе.