Skip to content

Commit

Permalink
Revised logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ljachymczyk committed Aug 4, 2014
1 parent ac11319 commit 6072b8a
Show file tree
Hide file tree
Showing 36 changed files with 879 additions and 1,050 deletions.
2 changes: 1 addition & 1 deletion .rspec
@@ -1,5 +1,5 @@
--color
--format=documentation
#--format=documentation
--backtrace
--profile
--order random
2 changes: 2 additions & 0 deletions Rakefile
Expand Up @@ -12,6 +12,8 @@ rescue LoadError
RDoc::Task = Rake::RDocTask
end

require 'thor'

RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'MailyHerald'
Expand Down
8 changes: 4 additions & 4 deletions app/mailers/maily_herald/mailer.rb
Expand Up @@ -2,11 +2,11 @@ module MailyHerald
class Mailer < ActionMailer::Base
attr_reader :entity

def generic entity, mailing, subscription
destination = subscription.destination
def generic entity, mailing
destination = mailing.destination(entity)
subject = mailing.subject
from = mailing.sender
content = subscription.is_a?(MailyHerald::SequenceSubscription) ? subscription.render_template(mailing) : subscription.render_template
content = mailing.render_template(entity)

mail(to: destination, from: from, subject: subject) do |format|
format.text { render text: content }
Expand All @@ -20,7 +20,7 @@ def deliver_mail(mail) #:nodoc:
entity = mail.maily_herald_data[:entity]

if mailing && entity
mailing.deliver_to(entity) do
mailing.deliver_with_mailer_to(entity) do
ActiveSupport::Notifications.instrument("deliver.action_mailer") do |payload|
self.set_payload_for_mail(payload, mail)
yield # Let Mail do the delivery actions
Expand Down
25 changes: 0 additions & 25 deletions app/models/maily_herald/aggregated_subscription.rb

This file was deleted.

27 changes: 12 additions & 15 deletions app/models/maily_herald/dispatch.rb
@@ -1,22 +1,19 @@
module MailyHerald
class Dispatch < ActiveRecord::Base
belongs_to :list, :class_name => "MailyHerald::List"

validates :name, :presence => true, :format => {:with => /^\w+$/}, :uniqueness => true
validates :list, :presence => true

delegate :subscription_for, :to => :list

def list= l
l = MailyHerald::List.find_by_name(l.to_s) if l.is_a?(String) || l.is_a?(Symbol)
super(l)
end

def subscription_for entity
subscription = self.subscriptions.for_entity(entity).first
unless subscription
subscription = self.subscriptions.build
subscription.entity = entity
if self.autosubscribe && self.context.scope.include?(entity)
if entity.respond_to?(:maily_herald_autosubscribe)
subscription.active = entity.maily_herald_autosubscribe(self)
else
subscription.active = true
end
end
subscription.save!
end
subscription
def processable? entity
self.enabled? && (self.override_subscription? || self.list.subscribed?(entity))
end

end
Expand Down
61 changes: 61 additions & 0 deletions app/models/maily_herald/list.rb
@@ -0,0 +1,61 @@
module MailyHerald
class List < ActiveRecord::Base
attr_accessible :token_action, :context_name

has_many :subscriptions, :class_name => "MailyHerald::Subscription"

after_initialize do
if self.new_record?
self.token_action = :unsubscribe
end
end

def context
@context ||= MailyHerald.context self.context_name
end

def subscribe! entity
s = subscription_for(entity)
s ? s.activate! : s = create_subscription_for(entity, true)
s
end

def unsubscribe! entity
s = subscription_for(entity)
s ? s.deactivate! : s = create_subscription_for(entity, false)
s
end

def subscribed? entity
!!subscription_for(entity).try(:active?)
end

def subscription_for entity
self.subscriptions.for_entity(entity).first
end

def token_action
read_attribute(:token_action).to_sym
end

def token_custom_action &block
if block_given?
MailyHerald.token_custom_action :mailing, self.id, &block
else
MailyHerald.token_custom_action :mailing, self.id
end
end

private

def create_subscription_for entity, active = false
s = self.subscriptions.build.tap do |s|
s.entity = entity
s.active = active
end
s.save!
s
end

end
end
18 changes: 15 additions & 3 deletions app/models/maily_herald/log.rb
@@ -1,28 +1,36 @@
module MailyHerald
class Log < ActiveRecord::Base
AVAILABLE_STATUSES = [:delivered, :skipped, :error]
AVAILABLE_STATUSES = [:scheduled, :delivered, :skipped, :error]

belongs_to :entity, :polymorphic => true
belongs_to :mailing, :class_name => "MailyHerald::Mailing", :foreign_key => :mailing_id
belongs_to :sequence, :class_name => "MailyHerald::Sequence", :foreign_key => :sequence_id

validates :entity, :presence => true
validates :mailing, :presence => true
validates :status, :presence => true, :inclusion => {:in => AVAILABLE_STATUSES}

default_scope order("processed_at asc")
validates :processing_at, :presence => true, :if => :scheduled?

default_scope order("processing_at asc")
scope :for_entity, lambda {|entity| where(:entity_id => entity.id, :entity_type => entity.class.base_class) }
scope :for_mailing, lambda {|mailing| where(:mailing_id => mailing.id) }
scope :for_sequence, lambda {|sequence| where(:sequence_id => sequence.id) }
scope :delivered, where(:status => :delivered)
scope :skipped, where(:status => :skipped)
scope :error, where(:status => :error)
scope :scheduled, where(:status => :scheduled)
scope :processed, where(:status => [:delivered, :skipped, :error])

serialize :data, Hash

attr_accessible :status, :data

def self.create_for mailing, entity, status = :delivered, data = nil
log = Log.new
log.mailing = mailing
log.entity = entity
log.processed_at = DateTime.now
log.processing_at = DateTime.now
log.status = status
log.data = data if data
log.save!
Expand All @@ -44,5 +52,9 @@ def skipped?
def error?
self.status == :error
end

def scheduled?
self.status == :scheduled
end
end
end
99 changes: 42 additions & 57 deletions app/models/maily_herald/mailing.rb
@@ -1,16 +1,12 @@
module MailyHerald
MailyHerald::SubscriptionGroup

class Mailing < Dispatch
attr_accessible :title, :subject, :context_name, :autosubscribe, :subscription_group, :override_subscription,
:token_action, :sequence, :conditions, :mailer_name, :title, :from, :relative_delay, :template, :start, :start_var, :period
include MailyHerald::TemplateRenderer

has_many :subscriptions, :class_name => "MailyHerald::MailingSubscription", :foreign_key => "dispatch_id", :dependent => :destroy
has_many :logs, :class_name => "MailyHerald::Log", :dependent => :destroy
attr_accessible :title, :subject, :context_name, :override_subscription,
:sequence, :conditions, :mailer_name, :title, :from, :relative_delay, :template, :start_at, :period

belongs_to :subscription_group, :class_name => "MailyHerald::SubscriptionGroup"
has_many :logs, :class_name => "MailyHerald::Log", :dependent => :destroy

validates :trigger, :presence => true, :inclusion => {:in => [:manual, :create, :save, :update, :destroy]}
validates :title, :presence => true
validates :subject, :presence => true, :if => :generic_mailer?
validates :template, :presence => true, :if => :generic_mailer?
Expand All @@ -25,22 +21,11 @@ class Mailing < Dispatch

after_initialize do
if self.new_record?
self.autosubscribe = true
self.override_subscription = false
self.token_action = :unsubscribe
self.mailer_name = :generic
end
end

def subscription_group= g
g = MailyHerald::SubscriptionGroup.find_by_name(g.to_s) if g.is_a?(String) || g.is_a?(Symbol)
super(g)
end

def token_action
read_attribute(:token_action).to_sym
end

def enabled?
self.enabled
end
Expand All @@ -57,10 +42,6 @@ def sequence?
self.class == SequenceMailing
end

def context
@context ||= MailyHerald.context context_name
end

def sender
if self.from && !self.from.empty?
self.from
Expand All @@ -69,55 +50,59 @@ def sender
end
end

def trigger
(read_attribute(:trigger) || :manual).to_sym
def has_conditions?
self.conditions && !self.conditions.empty?
end
def trigger=(value)
write_attribute(:trigger, value.to_s)

def generic_mailer?
self.mailer_name == "generic"
end

def token_custom_action &block
if block_given?
MailyHerald.token_custom_action :mailing, self.id, &block
else
MailyHerald.token_custom_action :mailing, self.id
end
def conditions_met? entity
subscription = self.list.subscription_for(entity)
return false unless subscription

evaluator = Utils::MarkupEvaluator.new(self.list.context.drop_for(entity, subscription))
evaluator.evaluate_conditions(self.conditions)
end

def has_conditions?
self.conditions && !self.conditions.empty?
def destination entity
self.list.context.destination.call(entity)
end

def generic_mailer?
self.mailer_name == "generic"
def render_template entity
subscription = self.list.subscription_for(entity)
return unless subscription

drop = self.list.context.drop_for entity, subscription
perform_template_rendering drop, self.template
end

protected

def deliver_to entity
if block_given?
# Called from Mailer
subscription = subscription_for entity
return unless subscription.processable?
unless subscription.conditions_met?(self)
Log.create_for self, entity, :skipped
return
end

mail = yield # Let mailer do his job

Log.create_for self, entity, :delivered, {:content => mail.first.to_s}
if self.mailer_name == 'generic'
subscription = self.list.subscription_for entity
mail = Mailer.generic(entity, self)
else
if self.mailer_name == 'generic'
subscription = subscription_for entity
mail = Mailer.generic(entity, self, subscription)
else
mail = self.mailer_name.constantize.send(self.name, entity)
end
mail.deliver
mail = self.mailer_name.constantize.send(self.name, entity)
end

mail.deliver
end

# Called from Mailer, block required
def deliver_with_mailer_to entity
return unless processable?(entity)
unless conditions_met?(entity)
return {status: :skipped}
end

mail = yield # Let mailer do his job

return {status: :delivered, data: {:content => mail.to_s}}
rescue StandardError => e
Log.create_for self, entity, :error, {:msg => e.to_s}
return {status: :error, data: {:msg => e.to_s}}
end

private
Expand Down

0 comments on commit 6072b8a

Please sign in to comment.