jam-cloud/ruby/lib/jam_ruby/models/email_batch.rb

228 lines
5.9 KiB
Ruby
Raw Normal View History

module JamRuby
class EmailBatch < ActiveRecord::Base
self.table_name = "email_batches"
2014-04-05 18:52:12 +00:00
has_many :email_batch_sets, :class_name => 'JamRuby::EmailBatchSet'
2014-04-04 10:08:00 +00:00
2014-03-19 16:32:53 +00:00
attr_accessible :from_email, :subject, :test_emails, :body
2014-04-05 21:25:47 +00:00
attr_accessible :lock_version, :opt_in_count, :sent_count, :started_at, :completed_at
2014-04-05 18:52:12 +00:00
default_scope { order('created_at DESC') }
2014-03-18 18:33:48 +00:00
VAR_FIRST_NAME = '@FIRSTNAME'
VAR_LAST_NAME = '@LASTNAME'
DEFAULT_SENDER = "JamKazam <noreply@jamkazam.com>"
2014-05-11 09:43:40 +00:00
BATCH_SIZE = 500
2014-04-03 05:03:28 +00:00
BODY_TEMPLATE =<<FOO
Hello #{VAR_FIRST_NAME},
2014-04-05 18:52:12 +00:00
<p>Paragraph 1 ... newline whitespace is significant for plain text conversions</p>
2014-04-03 05:03:28 +00:00
2014-04-05 22:16:32 +00:00
<p>Paragraph 2 ... "#{VAR_FIRST_NAME}" will be replaced by users first name</p>
2014-04-03 05:03:28 +00:00
<p>Thanks for using JamKazam!</p>
FOO
include AASM
aasm do
state :pending, :initial => true
state :testing
state :tested
2014-04-05 21:25:47 +00:00
state :delivering
state :delivered
state :disabled
state :snapshot
event :enable do
transitions :from => :disabled, :to => :pending
end
2014-04-05 21:25:47 +00:00
event :reset, :after => :did_reset do
transitions :from => [:disabled, :testing, :tested, :delivering, :delivered, :pending], :to => :pending
2014-03-19 16:32:53 +00:00
end
2014-04-05 21:25:47 +00:00
event :do_test_run, :before => :will_run_tests do
transitions :from => [:pending, :tested, :delivered], :to => :testing
end
2014-03-19 16:32:53 +00:00
event :did_test_run, :after => :ran_tests do
transitions :from => :testing, :to => :tested
end
2014-04-05 21:25:47 +00:00
event :do_batch_run, :before => :will_run_batch do
transitions :from => [:tested, :pending, :delivered], :to => :delivering
end
2014-03-19 16:32:53 +00:00
event :did_batch_run, :after => :ran_batch do
2014-04-05 21:25:47 +00:00
transitions :from => :delivering, :to => :delivered
end
event :disable do
2014-04-05 21:25:47 +00:00
transitions :from => [:pending, :tested, :delivered], :to => :disabled
2014-04-05 18:52:12 +00:00
end
event :snapshoting, :after => :take_snapshot do
transitions :from => [:pending], :to => :snapshot
end
2014-04-05 18:52:12 +00:00
end
def self.new(*args)
oo = super
oo.body = BODY_TEMPLATE
oo
end
2014-03-19 16:32:53 +00:00
def self.create_with_params(params)
obj = self.new
params.each { |kk,vv| vv.strip! }
obj.update_with_conflict_validation(params)
2014-03-19 16:32:53 +00:00
obj
end
2014-04-05 18:52:12 +00:00
def can_run_batch?
self.tested? || self.pending?
end
def can_run_test?
self.test_emails.present? && (self.tested? || self.pending?)
end
2014-05-16 07:58:06 +00:00
def deliver_batch_sets!
User.email_opt_in.find_each do |user|
bset = EmailBatchSet.sent_email(self, user.id)
2014-05-16 07:58:06 +00:00
if 'test' == Rails.env
BatchMailer.send_batch_email(self.id, bset.user_id).deliver!
2014-05-16 07:58:06 +00:00
else
BatchMailer.send_batch_email(self.id, bset.user_id).deliver_now
2014-05-16 07:58:06 +00:00
end
2014-04-04 10:23:20 +00:00
end
end
2014-05-16 07:58:06 +00:00
def deliver_batch
self.perform_event('do_batch_run!')
self.deliver_batch_sets!
end
def deliver_batch_async
BatchEmailJob.enqueue(self.id)
end
2014-03-19 07:15:38 +00:00
def test_count
self.test_emails.split(',').count
end
2014-03-18 18:33:48 +00:00
def test_users
self.test_emails.split(',').collect do |ee|
ee.strip!
uu = User.new
uu.email = ee
uu.first_name = ee.match(/^(.*)@/)[1].to_s
uu.last_name = 'Test'
uu
end
end
def send_test_batch
2014-03-19 16:32:53 +00:00
self.perform_event('do_test_run!')
2014-04-09 21:11:13 +00:00
if 'test' == Rails.env
2014-04-05 21:25:47 +00:00
BatchMailer.send_batch_email_test(self.id).deliver!
2014-04-05 18:52:12 +00:00
else
BatchMailer.send_batch_email_test(self.id).deliver_now
2014-04-05 18:52:12 +00:00
end
2014-03-18 18:33:48 +00:00
end
def merged_body(user)
body.gsub(VAR_FIRST_NAME, user.first_name).gsub(VAR_LAST_NAME, user.last_name)
end
2014-03-19 06:20:58 +00:00
def did_send(emails)
self.update_with_conflict_validation({ :sent_count => self.sent_count + emails.size })
2014-04-05 21:25:47 +00:00
if self.sent_count >= self.opt_in_count
if delivering?
2014-03-19 16:32:53 +00:00
self.perform_event('did_batch_run!')
elsif testing?
2014-03-19 16:32:53 +00:00
self.perform_event('did_test_run!')
end
end
end
2014-03-19 16:32:53 +00:00
def perform_event(event_name)
num_try = 0
self.send(event_name)
rescue ActiveRecord::StaleObjectError
num_try += 1
if 5 > num_try
self.reload
retry
end
end
def update_with_conflict_validation(*args)
num_try = 0
2014-04-05 21:25:47 +00:00
begin
update_attributes(*args)
rescue ActiveRecord::StaleObjectError
num_try += 1
if 5 > num_try
self.reload
sleep(0.25)
retry
end
end
end
2014-03-19 16:32:53 +00:00
2014-04-05 21:25:47 +00:00
def will_run_batch
self.update_with_conflict_validation({:opt_in_count => User.email_opt_in.count,
2014-03-19 16:32:53 +00:00
:sent_count => 0,
:started_at => Time.now
})
end
2014-04-05 21:25:47 +00:00
def will_run_tests
self.update_with_conflict_validation({:opt_in_count => self.test_count,
:sent_count => 0
2014-03-19 16:32:53 +00:00
})
end
def ran_tests
self.update_with_conflict_validation({ :completed_at => Time.now })
end
def ran_batch
self.update_with_conflict_validation({ :completed_at => Time.now })
2014-04-05 18:52:12 +00:00
end
def take_snapshot
end
2014-04-05 18:52:12 +00:00
def clone
bb = EmailBatch.new
bb.subject = self.subject
bb.body = self.body
bb.from_email = self.from_email
bb.test_emails = self.test_emails
bb.save!
bb
end
def opting_in_count
2014-04-05 21:25:47 +00:00
0 < opt_in_count ? opt_in_count : User.email_opt_in.count
end
def did_reset
self.email_batch_sets.map(&:destroy)
self.update_with_conflict_validation({
:opt_in_count => 0,
:sent_count => 0,
:started_at => nil,
:completed_at => nil,
})
end
2014-05-16 07:58:06 +00:00
def batch_substitutions(users=[])
{}
end
def body_for_users(users=[])
self.body
end
end
end