smailer 0.7.8 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,88 +1,105 @@
1
1
  class CreateSmailerTables < ActiveRecord::Migration
2
2
  def self.up
3
- create_table "mailing_lists", :force => true do |t|
4
- t.string "name"
3
+ create_table "finished_mails", :force => :cascade do |t|
4
+ t.integer "mail_campaign_id"
5
+ t.string "from"
6
+ t.string "to"
7
+ t.string "subject"
8
+ t.text "body_html"
9
+ t.integer "retries"
10
+ t.datetime "last_retry_at"
11
+ t.string "last_error"
12
+ t.datetime "sent_at"
13
+ t.integer "status"
5
14
  t.datetime "created_at"
6
15
  t.datetime "updated_at"
16
+ t.text "body_text"
17
+ t.boolean "opened", :default => false, :null => false
18
+ t.string "key"
7
19
  end
8
20
 
9
- create_table "mail_campaigns", :force => true do |t|
21
+ add_index "finished_mails", ["key"], :name => "index_finished_mails_on_key", :unique => true
22
+ add_index "finished_mails", ["mail_campaign_id", "status"], :name => "index_finished_mails_on_mail_campain_id_and_status"
23
+ add_index "finished_mails", ["to", "mail_campaign_id"], :name => "index_finished_mails_on_to_and_mail_campaign_id"
24
+
25
+ create_table "mail_attachments", :force => :cascade do |t|
26
+ t.string "filename", :null => false
27
+ t.string "path", :limit => 2048
28
+ t.datetime "created_at"
29
+ t.datetime "updated_at"
30
+ t.integer "mail_template_id"
31
+ end
32
+
33
+ add_index "mail_attachments", ["mail_template_id"], :name => "index_mail_attachments_on_mail_template_id"
34
+
35
+ create_table "mail_campaigns", :force => :cascade do |t|
10
36
  t.integer "mailing_list_id"
11
- t.string "from"
12
- t.string "subject"
13
- t.text "body_html"
14
37
  t.integer "unsubscribe_methods"
15
38
  t.datetime "created_at"
16
39
  t.datetime "updated_at"
17
- t.text "body_text"
18
40
  t.integer "sent_mails_count", :default => 0, :null => false
19
41
  t.integer "opened_mails_count", :default => 0, :null => false
20
42
  end
43
+
21
44
  add_index "mail_campaigns", ["mailing_list_id"], :name => "index_mail_campaigns_on_mailing_list_id"
22
45
 
23
- create_table "queued_mails", :force => true do |t|
46
+ create_table "mail_keys", :force => :cascade do |t|
47
+ t.string "email"
48
+ t.string "key"
49
+ t.datetime "created_at"
50
+ t.datetime "updated_at"
51
+ end
52
+
53
+ add_index "mail_keys", ["email"], :name => "index_mail_keys_on_email", :unique => true
54
+ add_index "mail_keys", ["key"], :name => "index_mail_keys_on_key", :unique => true
55
+
56
+ create_table "mail_templates", :force => :cascade do |t|
24
57
  t.integer "mail_campaign_id"
25
- t.string "to"
26
- t.integer "retries", :default => 0, :null => false
27
- t.datetime "last_retry_at"
28
- t.string "last_error"
29
- t.boolean "locked", :default => false, :null => false
30
- t.datetime "locked_at"
58
+ t.integer "queued_mail_id"
59
+ t.string "from"
60
+ t.string "subject"
61
+ t.text "body_html"
62
+ t.text "body_text"
31
63
  t.datetime "created_at"
32
64
  t.datetime "updated_at"
33
- t.string "key"
34
65
  end
35
- add_index "queued_mails", ["mail_campaign_id", "to"], :name => "index_queued_mails_on_mail_campain_id_and_to", :unique => true
36
- add_index "queued_mails", ["retries", "locked"], :name => "index_queued_mails_on_retries_and_locked"
37
- add_index "queued_mails", ["locked", "retries", "id"], :name => "index_queued_mails_on_locked_retries_and_id"
38
- add_index "queued_mails", ["locked", "locked_at"], :name => "index_queued_mails_on_locked_and_locked_at"
39
66
 
40
- create_table "mail_campaign_attachments", :force => true do |t|
41
- t.integer "mail_campaign_id", :null => false
42
- t.string "filename", :null => false
43
- t.string "path", :limit => 2048
67
+ add_index "mail_templates", ["mail_campaign_id"], :name => "index_mail_templates_on_mail_campaign_id"
68
+ add_index "mail_templates", ["queued_mail_id"], :name => "index_mail_templates_on_queued_mail_id"
69
+
70
+ create_table "mailing_lists", :force => :cascade do |t|
71
+ t.string "name"
44
72
  t.datetime "created_at"
45
73
  t.datetime "updated_at"
46
74
  end
47
- add_index "mail_campaign_attachments", "mail_campaign_id"
48
75
 
49
- create_table "finished_mails", :force => true do |t|
76
+ create_table "queued_mails", :force => :cascade do |t|
50
77
  t.integer "mail_campaign_id"
51
- t.string "from"
52
78
  t.string "to"
53
- t.string "subject"
54
- t.text "body_html"
55
- t.integer "retries"
79
+ t.integer "retries", :default => 0, :null => false
56
80
  t.datetime "last_retry_at"
57
81
  t.string "last_error"
58
- t.datetime "sent_at"
59
- t.integer "status"
82
+ t.boolean "locked", :default => false, :null => false
83
+ t.datetime "locked_at"
60
84
  t.datetime "created_at"
61
85
  t.datetime "updated_at"
62
- t.text "body_text"
63
- t.boolean "opened", :default => false, :null => false
64
86
  t.string "key"
87
+ t.boolean "require_uniqueness", :default => true
65
88
  end
66
- add_index "finished_mails", ["key"], :name => "index_finished_mails_on_key", :unique => true
67
- add_index "finished_mails", ["mail_campaign_id", "status"], :name => "index_finished_mails_on_mail_campain_id_and_status"
68
- add_index "finished_mails", ["to", "mail_campaign_id"], :name => "index_finished_mails_on_to_and_mail_campaign_id"
69
89
 
70
- create_table "mail_keys", :force => true do |t|
71
- t.string "email"
72
- t.string "key"
73
- t.datetime "created_at"
74
- t.datetime "updated_at"
75
- end
76
- add_index "mail_keys", ["email"], :name => "index_mail_keys_on_email", :unique => true
77
- add_index "mail_keys", ["key"], :name => "index_mail_keys_on_key", :unique => true
90
+ add_index "queued_mails", ["locked", "locked_at"], :name => "index_queued_mails_on_locked_and_locked_at"
91
+ add_index "queued_mails", ["locked", "retries", "id"], :name => "index_queued_mails_on_locked_retries_and_id"
92
+ add_index "queued_mails", ["mail_campaign_id", "to", "require_uniqueness"], :name => "index_queued_mails_uniqueness_for_to", :unique => true
93
+ add_index "queued_mails", ["retries", "locked"], :name => "index_queued_mails_on_retries_and_locked"
78
94
 
79
- create_table "smailer_properties", :force => true do |t|
95
+ create_table "smailer_properties", :force => :cascade do |t|
80
96
  t.string "name"
81
97
  t.text "value"
82
98
  t.datetime "created_at"
83
99
  t.datetime "updated_at"
84
100
  t.string "notes"
85
101
  end
102
+
86
103
  add_index "smailer_properties", ["name"], :name => "index_smailer_properties_on_name", :unique => true
87
104
  end
88
105
 
@@ -91,8 +108,9 @@ class CreateSmailerTables < ActiveRecord::Migration
91
108
  drop_table :mail_keys
92
109
  drop_table :finished_mails
93
110
  drop_table :queued_mails
94
- drop_table :mail_campaign_attachments
111
+ drop_table :mail_attachments
95
112
  drop_table :mail_campaigns
113
+ drop_table :mail_templates
96
114
  drop_table :mailing_lists
97
115
  end
98
- end
116
+ end
@@ -1,88 +1,105 @@
1
1
  class CreateSmailerTables < ActiveRecord::Migration
2
2
  def self.up
3
- create_table "mailing_lists", :force => true do |t|
4
- t.string "name"
3
+ create_table "finished_mails", :force => :cascade do |t|
4
+ t.integer "mail_campaign_id"
5
+ t.string "from"
6
+ t.string "to"
7
+ t.string "subject"
8
+ t.text "body_html"
9
+ t.integer "retries"
10
+ t.datetime "last_retry_at"
11
+ t.string "last_error"
12
+ t.datetime "sent_at"
13
+ t.integer "status"
5
14
  t.datetime "created_at"
6
15
  t.datetime "updated_at"
16
+ t.text "body_text"
17
+ t.boolean "opened", :default => false, :null => false
18
+ t.string "key"
7
19
  end
8
20
 
9
- create_table "mail_campaigns", :force => true do |t|
21
+ add_index "finished_mails", ["key"], :name => "index_finished_mails_on_key", :unique => true
22
+ add_index "finished_mails", ["mail_campaign_id", "status"], :name => "index_finished_mails_on_mail_campain_id_and_status"
23
+ add_index "finished_mails", ["to", "mail_campaign_id"], :name => "index_finished_mails_on_to_and_mail_campaign_id"
24
+
25
+ create_table "mail_attachments", :force => :cascade do |t|
26
+ t.string "filename", :null => false
27
+ t.string "path", :limit => 2048
28
+ t.datetime "created_at"
29
+ t.datetime "updated_at"
30
+ t.integer "mail_template_id"
31
+ end
32
+
33
+ add_index "mail_attachments", ["mail_template_id"], :name => "index_mail_attachments_on_mail_template_id"
34
+
35
+ create_table "mail_campaigns", :force => :cascade do |t|
10
36
  t.integer "mailing_list_id"
11
- t.string "from"
12
- t.string "subject"
13
- t.text "body_html"
14
37
  t.integer "unsubscribe_methods"
15
38
  t.datetime "created_at"
16
39
  t.datetime "updated_at"
17
- t.text "body_text"
18
40
  t.integer "sent_mails_count", :default => 0, :null => false
19
41
  t.integer "opened_mails_count", :default => 0, :null => false
20
42
  end
43
+
21
44
  add_index "mail_campaigns", ["mailing_list_id"], :name => "index_mail_campaigns_on_mailing_list_id"
22
45
 
23
- create_table "queued_mails", :force => true do |t|
46
+ create_table "mail_keys", :force => :cascade do |t|
47
+ t.string "email"
48
+ t.string "key"
49
+ t.datetime "created_at"
50
+ t.datetime "updated_at"
51
+ end
52
+
53
+ add_index "mail_keys", ["email"], :name => "index_mail_keys_on_email", :unique => true
54
+ add_index "mail_keys", ["key"], :name => "index_mail_keys_on_key", :unique => true
55
+
56
+ create_table "mail_templates", :force => :cascade do |t|
24
57
  t.integer "mail_campaign_id"
25
- t.string "to"
26
- t.integer "retries", :default => 0, :null => false
27
- t.datetime "last_retry_at"
28
- t.string "last_error"
29
- t.boolean "locked", :default => false, :null => false
30
- t.datetime "locked_at"
58
+ t.integer "queued_mail_id"
59
+ t.string "from"
60
+ t.string "subject"
61
+ t.text "body_html"
62
+ t.text "body_text"
31
63
  t.datetime "created_at"
32
64
  t.datetime "updated_at"
33
- t.string "key"
34
65
  end
35
- add_index "queued_mails", ["mail_campaign_id", "to"], :name => "index_queued_mails_on_mail_campain_id_and_to", :unique => true
36
- add_index "queued_mails", ["retries", "locked"], :name => "index_queued_mails_on_retries_and_locked"
37
- add_index "queued_mails", ["locked", "retries", "id"], :name => "index_queued_mails_on_locked_retries_and_id"
38
- add_index "queued_mails", ["locked", "locked_at"], :name => "index_queued_mails_on_locked_and_locked_at"
39
66
 
40
- create_table "mail_campaign_attachments", :force => true do |t|
41
- t.integer "mail_campaign_id", :null => false
42
- t.string "filename", :null => false
43
- t.string "path", :limit => 2048
67
+ add_index "mail_templates", ["mail_campaign_id"], :name => "index_mail_templates_on_mail_campaign_id"
68
+ add_index "mail_templates", ["queued_mail_id"], :name => "index_mail_templates_on_queued_mail_id"
69
+
70
+ create_table "mailing_lists", :force => :cascade do |t|
71
+ t.string "name"
44
72
  t.datetime "created_at"
45
73
  t.datetime "updated_at"
46
74
  end
47
- add_index "mail_campaign_attachments", "mail_campaign_id"
48
75
 
49
- create_table "finished_mails", :force => true do |t|
76
+ create_table "queued_mails", :force => :cascade do |t|
50
77
  t.integer "mail_campaign_id"
51
- t.string "from"
52
78
  t.string "to"
53
- t.string "subject"
54
- t.text "body_html"
55
- t.integer "retries"
79
+ t.integer "retries", :default => 0, :null => false
56
80
  t.datetime "last_retry_at"
57
81
  t.string "last_error"
58
- t.datetime "sent_at"
59
- t.integer "status"
82
+ t.boolean "locked", :default => false, :null => false
83
+ t.datetime "locked_at"
60
84
  t.datetime "created_at"
61
85
  t.datetime "updated_at"
62
- t.text "body_text"
63
- t.boolean "opened", :default => false, :null => false
64
86
  t.string "key"
87
+ t.boolean "require_uniqueness", :default => true
65
88
  end
66
- add_index "finished_mails", ["key"], :name => "index_finished_mails_on_key", :unique => true
67
- add_index "finished_mails", ["mail_campaign_id", "status"], :name => "index_finished_mails_on_mail_campain_id_and_status"
68
- add_index "finished_mails", ["to", "mail_campaign_id"], :name => "index_finished_mails_on_to_and_mail_campaign_id"
69
89
 
70
- create_table "mail_keys", :force => true do |t|
71
- t.string "email"
72
- t.string "key"
73
- t.datetime "created_at"
74
- t.datetime "updated_at"
75
- end
76
- add_index "mail_keys", ["email"], :name => "index_mail_keys_on_email", :unique => true
77
- add_index "mail_keys", ["key"], :name => "index_mail_keys_on_key", :unique => true
90
+ add_index "queued_mails", ["locked", "locked_at"], :name => "index_queued_mails_on_locked_and_locked_at"
91
+ add_index "queued_mails", ["locked", "retries", "id"], :name => "index_queued_mails_on_locked_retries_and_id"
92
+ add_index "queued_mails", ["mail_campaign_id", "to", "require_uniqueness"], :name => "index_queued_mails_uniqueness_for_to", :unique => true
93
+ add_index "queued_mails", ["retries", "locked"], :name => "index_queued_mails_on_retries_and_locked"
78
94
 
79
- create_table "smailer_properties", :force => true do |t|
95
+ create_table "smailer_properties", :force => :cascade do |t|
80
96
  t.string "name"
81
97
  t.text "value"
82
98
  t.datetime "created_at"
83
99
  t.datetime "updated_at"
84
100
  t.string "notes"
85
101
  end
102
+
86
103
  add_index "smailer_properties", ["name"], :name => "index_smailer_properties_on_name", :unique => true
87
104
  end
88
105
 
@@ -91,8 +108,9 @@ class CreateSmailerTables < ActiveRecord::Migration
91
108
  drop_table :mail_keys
92
109
  drop_table :finished_mails
93
110
  drop_table :queued_mails
94
- drop_table :mail_campaign_attachments
111
+ drop_table :mail_attachments
95
112
  drop_table :mail_campaigns
113
+ drop_table :mail_templates
96
114
  drop_table :mailing_lists
97
115
  end
98
- end
116
+ end
@@ -1,11 +1,12 @@
1
1
  module Smailer
2
2
  module Models
3
3
  autoload :MailingList, 'smailer/models/mailing_list'
4
+ autoload :MailTemplate, 'smailer/models/mail_template'
4
5
  autoload :MailCampaign, 'smailer/models/mail_campaign'
5
- autoload :MailCampaignAttachment, 'smailer/models/mail_campaign_attachment'
6
+ autoload :MailAttachment, 'smailer/models/mail_attachment'
6
7
  autoload :MailKey, 'smailer/models/mail_key'
7
8
  autoload :QueuedMail, 'smailer/models/queued_mail'
8
9
  autoload :FinishedMail, 'smailer/models/finished_mail'
9
10
  autoload :Property, 'smailer/models/property'
10
11
  end
11
- end
12
+ end
@@ -2,18 +2,16 @@ require 'open-uri'
2
2
 
3
3
  module Smailer
4
4
  module Models
5
- class MailCampaignAttachment < ActiveRecord::Base
5
+ class MailAttachment < ActiveRecord::Base
6
+ belongs_to :mail_template, :inverse_of => :attachments
6
7
 
7
- belongs_to :mail_campaign
8
- validates_presence_of :mail_campaign_id
9
- validates_numericality_of :mail_campaign_id
10
8
  validates_presence_of :path
11
9
  validates_presence_of :filename
10
+ validates_presence_of :mail_template
12
11
 
13
12
  def body
14
13
  open(self.path).read
15
14
  end
16
-
17
15
  end
18
16
  end
19
17
  end
@@ -10,8 +10,11 @@ module Smailer
10
10
  belongs_to :mailing_list
11
11
  has_many :queued_mails, :dependent => :destroy
12
12
  has_many :finished_mails, :dependent => :destroy
13
- has_many :attachments,
14
- :class_name => '::Smailer::Models::MailCampaignAttachment'
13
+
14
+ has_one :mail_template, :dependent => :destroy, :autosave => true, :inverse_of => :mail_campaign
15
+
16
+ delegate :from, :subject, :body_html, :body_text, :to => :my_mail_template, :allow_nil => true
17
+ delegate :from=, :subject=, :body_html=, :body_text=, :to => :my_mail_template
15
18
 
16
19
  validates_presence_of :mailing_list_id, :from
17
20
  validates_numericality_of :mailing_list_id, :unsubscribe_methods, :only_integer => true, :allow_nil => true
@@ -54,8 +57,12 @@ module Smailer
54
57
  opened_mails_count.to_f / sent_mails_count
55
58
  end
56
59
 
60
+ def attachments
61
+ my_mail_template.attachments
62
+ end
63
+
57
64
  def add_attachment(filename, path)
58
- self.attachments.create!(:filename => filename, :path => path)
65
+ my_mail_template.attachments.build(:filename => filename, :path => path)
59
66
  end
60
67
 
61
68
  def self.unsubscribe_methods
@@ -69,6 +76,10 @@ module Smailer
69
76
 
70
77
  private
71
78
 
79
+ def my_mail_template
80
+ mail_template || build_mail_template
81
+ end
82
+
72
83
  def unsubscribe_methods_list_from(method_specification)
73
84
  if method_specification == :all
74
85
  self.class.unsubscribe_methods.keys
@@ -78,4 +89,4 @@ module Smailer
78
89
  end
79
90
  end
80
91
  end
81
- end
92
+ end
@@ -0,0 +1,13 @@
1
+ module Smailer
2
+ module Models
3
+ class MailTemplate < ActiveRecord::Base
4
+ belongs_to :mail_campaign, :inverse_of => :mail_template
5
+ belongs_to :queued_mail, :inverse_of => :mail_template
6
+
7
+ has_many :attachments, :class_name => '::Smailer::Models::MailAttachment', :autosave => true, :inverse_of => :mail_template
8
+
9
+ validates_presence_of :from
10
+ validates_length_of :from, :subject, :maximum => 255, :allow_nil => true
11
+ end
12
+ end
13
+ end
@@ -1,31 +1,39 @@
1
1
  require 'digest/md5'
2
+ require 'securerandom'
2
3
 
3
4
  module Smailer
4
5
  module Models
5
6
  class QueuedMail < ActiveRecord::Base
6
7
  belongs_to :mail_campaign
7
8
 
9
+ has_one :mail_template, :dependent => :destroy, :autosave => true, :inverse_of => :queued_mail
10
+ has_many :attachments, :through => :mail_template
11
+
8
12
  validates_presence_of :mail_campaign_id, :to
9
- validates_uniqueness_of :to, :scope => :mail_campaign_id
13
+ validates_uniqueness_of :to, :scope => :mail_campaign_id, :if => proc { |queued_mail| queued_mail.require_uniqueness }
10
14
  validates_uniqueness_of :key
11
15
  validates_numericality_of :mail_campaign_id, :retries, :only_integer => true, :allow_nil => true
12
16
  validates_length_of :to, :last_error, :maximum => 255, :allow_nil => true
13
17
 
14
18
  unless Smailer::Compatibility.rails_4?
15
- attr_accessible :mail_campaign_id, :to
19
+ attr_accessible :mail_campaign_id, :to, :from, :subject, :body_html, :body_text, :require_uniqueness
16
20
  end
17
21
 
18
- delegate :from, :subject, :mailing_list, :to => :mail_campaign, :allow_nil => true
19
-
20
22
  before_validation :initialize_message_key
21
23
  before_save :initialize_message_key
22
24
 
25
+ before_save :nullify_false_require_uniqueness
26
+
27
+ delegate :mailing_list, :to => :mail_campaign, :allow_nil => true
28
+ delegate :from, :subject, :to => :active_mail_template, :allow_nil => true
29
+ delegate :from=, :subject=, :body_html=, :body_text, :to => :my_mail_template
30
+
23
31
  def body_html
24
- interpolate mail_campaign.body_html
32
+ interpolate active_mail_template.body_html
25
33
  end
26
34
 
27
35
  def body_text
28
- interpolate mail_campaign.body_text
36
+ interpolate active_mail_template.body_text
29
37
  end
30
38
 
31
39
  def key
@@ -33,10 +41,39 @@ module Smailer
33
41
  self[:key]
34
42
  end
35
43
 
44
+ def attachments
45
+ active_mail_template.attachments
46
+ end
47
+
48
+ def add_attachment(filename, path)
49
+ my_mail_template.attachments.build(:filename => filename, :path => path)
50
+ end
51
+
36
52
  protected
37
53
 
54
+ def active_mail_template
55
+ mail_template || mail_campaign.try(:mail_template)
56
+ end
57
+
58
+ def my_mail_template
59
+ return mail_template if mail_template.present?
60
+
61
+ build_mail_template.tap do |template|
62
+ if mail_campaign.present?
63
+ campaign_template = mail_campaign.mail_template
64
+
65
+ template.from = campaign_template.from
66
+ template.subject = campaign_template.subject
67
+ template.body_html = campaign_template.body_html
68
+ template.body_text = campaign_template.body_text
69
+
70
+ template.attachments = campaign_template.attachments.map(&:dup)
71
+ end
72
+ end
73
+ end
74
+
38
75
  def initialize_message_key
39
- self.key = Digest::MD5.hexdigest("#{mail_campaign_id}, #{to} and #{id} compose this key.")
76
+ self.key = Digest::MD5.hexdigest("#{mail_campaign_id}, #{to}, #{SecureRandom.hex(15)} and #{id} compose this key.")
40
77
  end
41
78
 
42
79
  def interpolate(text)
@@ -57,6 +94,13 @@ module Smailer
57
94
 
58
95
  text
59
96
  end
97
+
98
+ # Prevents the unique index in the database from firing
99
+ def nullify_false_require_uniqueness
100
+ unless self.require_uniqueness
101
+ self.require_uniqueness = nil
102
+ end
103
+ end
60
104
  end
61
105
  end
62
106
  end