We were getting an exception in this case, which was OK I guess since this shouldn't happen if the application is used in a normal way, but we can simplify the code a little bit if we make the `recipients` code return an empty list of users. Note that the behavior of the `AdminNotification#list_of_recipients` and `Newsletter#list_of_recipient_emails` methods is now slightly different; previously they returned `nil` when given an invalid segment recipient, while now they return an empty array. I haven't found a place where this change is relevant. For example, in both of these models, the `deliver` method used to raise an exception when given an invalid segment while now it doesn't, but we always check the user segment is valid before calling the `deliver` method anyway, so it doesn't really affect the application.
69 lines
1.6 KiB
Ruby
69 lines
1.6 KiB
Ruby
class Newsletter < ApplicationRecord
|
|
has_many :activities, as: :actionable, inverse_of: :actionable
|
|
|
|
validates :subject, presence: true
|
|
validates :segment_recipient, presence: true
|
|
validates :from, presence: true, format: { with: /\A.+@.+\Z/ }
|
|
validates :body, presence: true
|
|
validate :validate_segment_recipient
|
|
|
|
acts_as_paranoid column: :hidden_at
|
|
include ActsAsParanoidAliases
|
|
|
|
def list_of_recipient_emails
|
|
UserSegments.user_segment_emails(segment_recipient)
|
|
end
|
|
|
|
def valid_segment_recipient?
|
|
UserSegments.valid_segment?(segment_recipient)
|
|
end
|
|
|
|
def draft?
|
|
sent_at.nil?
|
|
end
|
|
|
|
def deliver
|
|
run_at = first_batch_run_at
|
|
list_of_recipient_emails_in_batches.each do |recipient_emails|
|
|
recipient_emails.each do |recipient_email|
|
|
if valid_email?(recipient_email)
|
|
Mailer.delay(run_at: run_at).newsletter(self, recipient_email)
|
|
log_delivery(recipient_email)
|
|
end
|
|
end
|
|
run_at += batch_interval
|
|
end
|
|
end
|
|
|
|
def batch_size
|
|
10000
|
|
end
|
|
|
|
def batch_interval
|
|
20.minutes
|
|
end
|
|
|
|
def first_batch_run_at
|
|
Time.current
|
|
end
|
|
|
|
def list_of_recipient_emails_in_batches
|
|
list_of_recipient_emails.in_groups_of(batch_size, false)
|
|
end
|
|
|
|
private
|
|
|
|
def validate_segment_recipient
|
|
errors.add(:segment_recipient, :invalid) unless valid_segment_recipient?
|
|
end
|
|
|
|
def valid_email?(email)
|
|
email.match(/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i)
|
|
end
|
|
|
|
def log_delivery(recipient_email)
|
|
user = User.find_by(email: recipient_email)
|
|
Activity.log(user, :email, self)
|
|
end
|
|
end
|