maily_herald 0.0.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +10 -4
  3. data/.rspec +5 -0
  4. data/Gemfile +1 -12
  5. data/Gemfile.lock +129 -82
  6. data/Guardfile +25 -0
  7. data/LICENSE +10 -0
  8. data/README.md +346 -0
  9. data/Rakefile +5 -0
  10. data/app/controllers/maily_herald/tokens_controller.rb +11 -0
  11. data/app/helpers/maily_herald/tokens_helper.rb +17 -0
  12. data/app/mailers/maily_herald/mailer.rb +91 -0
  13. data/app/models/maily_herald/dispatch.rb +76 -0
  14. data/app/models/maily_herald/list.rb +99 -0
  15. data/app/models/maily_herald/log.rb +67 -0
  16. data/app/models/maily_herald/mailing.rb +139 -7
  17. data/app/models/maily_herald/one_time_mailing.rb +26 -0
  18. data/app/models/maily_herald/periodical_mailing.rb +145 -0
  19. data/app/models/maily_herald/sequence.rb +169 -2
  20. data/app/models/maily_herald/sequence_mailing.rb +71 -0
  21. data/app/models/maily_herald/subscription.rb +67 -0
  22. data/bin/maily_herald +16 -0
  23. data/config/database.yml +5 -0
  24. data/config/locales/en.yml +6 -11
  25. data/config/routes.rb +10 -0
  26. data/config/spring.rb +1 -0
  27. data/db/migrate/20150205120443_create_maily_herald_tables.rb +53 -0
  28. data/db/migrate_legacy/20130711124555_create_maily_herald_tables.rb +67 -0
  29. data/db/migrate_legacy/20140612101023_create_lists.rb +33 -0
  30. data/lib/generators/maily_herald/install_generator.rb +3 -3
  31. data/lib/generators/templates/README +2 -0
  32. data/lib/generators/templates/maily_herald.rb +1 -0
  33. data/lib/maily_herald.rb +345 -23
  34. data/lib/maily_herald/autonaming.rb +34 -0
  35. data/lib/maily_herald/capistrano.rb +5 -0
  36. data/lib/maily_herald/capistrano/tasks.cap +67 -0
  37. data/lib/maily_herald/capistrano/tasks2.rb +20 -0
  38. data/lib/maily_herald/cli.rb +293 -0
  39. data/lib/maily_herald/condition_evaluator.rb +82 -0
  40. data/lib/maily_herald/config.rb +5 -0
  41. data/lib/maily_herald/context.rb +223 -77
  42. data/lib/maily_herald/engine.rb +17 -0
  43. data/lib/maily_herald/logging.rb +90 -0
  44. data/lib/maily_herald/manager.rb +53 -0
  45. data/lib/maily_herald/model_extensions.rb +15 -0
  46. data/lib/maily_herald/template_renderer.rb +16 -0
  47. data/lib/maily_herald/utils.rb +78 -5
  48. data/lib/maily_herald/version.rb +1 -1
  49. data/maily_herald.gemspec +17 -9
  50. data/spec/controllers/maily_herald/tokens_controller_spec.rb +81 -0
  51. data/spec/dummy/Guardfile +35 -0
  52. data/spec/dummy/app/mailers/test_mailer.rb +11 -0
  53. data/spec/dummy/app/models/product.rb +2 -0
  54. data/spec/dummy/app/models/user.rb +4 -0
  55. data/spec/dummy/app/views/test_mailer/sample_mail.text.erb +1 -0
  56. data/spec/dummy/bin/rails +10 -0
  57. data/spec/dummy/bin/rake +7 -0
  58. data/spec/dummy/bin/rspec +7 -0
  59. data/spec/dummy/bin/spring +18 -0
  60. data/spec/dummy/config/application.rb +1 -1
  61. data/spec/dummy/config/environments/development.rb +1 -0
  62. data/spec/dummy/config/environments/test.rb +1 -0
  63. data/spec/dummy/config/initializers/maily_herald.rb +103 -0
  64. data/spec/dummy/config/locales/maily_herald.en.yml +28 -0
  65. data/spec/dummy/db/migrate/20130723074347_create_users.rb +18 -0
  66. data/spec/dummy/db/schema.rb +82 -0
  67. data/spec/factories/products.rb +5 -0
  68. data/spec/factories/users.rb +11 -0
  69. data/spec/lib/context_spec.rb +41 -0
  70. data/spec/lib/maily_herald_spec.rb +32 -0
  71. data/spec/lib/utils_spec.rb +48 -0
  72. data/spec/mailers/maily_herald/mailer_spec.rb +38 -0
  73. data/spec/models/maily_herald/list_spec.rb +64 -0
  74. data/spec/models/maily_herald/log_spec.rb +36 -0
  75. data/spec/models/maily_herald/mailing_spec.rb +34 -0
  76. data/spec/models/maily_herald/one_time_mailing_spec.rb +112 -0
  77. data/spec/models/maily_herald/periodical_mailing_spec.rb +339 -0
  78. data/spec/models/maily_herald/sequence_mailing_spec.rb +18 -0
  79. data/spec/models/maily_herald/sequence_spec.rb +429 -0
  80. data/spec/models/maily_herald/subscription_spec.rb +32 -0
  81. data/spec/spec_helper.rb +31 -11
  82. metadata +199 -54
  83. data/MIT-LICENSE +0 -20
  84. data/README.rdoc +0 -3
  85. data/app/assets/images/maily_herald/.gitkeep +0 -0
  86. data/app/assets/javascripts/maily_herald/application.js +0 -15
  87. data/app/assets/stylesheets/maily_herald/application.css +0 -13
  88. data/app/helpers/maily_herald/application_helper.rb +0 -4
  89. data/app/helpers/maily_herald_helper.rb +0 -9
  90. data/app/models/maily_herald/mailing_record.rb +0 -6
  91. data/app/views/layouts/maily_herald/application.html.erb +0 -14
  92. data/db/migrate/20130711124555_create_maily_herald_tables.rb +0 -38
  93. data/lib/maily_herald/worker.rb +0 -15
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe MailyHerald::OneTimeMailing do
4
+ before(:each) do
5
+ @entity = FactoryGirl.create :user
6
+
7
+ @list = MailyHerald.list(:generic_list)
8
+ expect(@list.context).to be_a(MailyHerald::Context)
9
+ end
10
+
11
+ describe "with subscription" do
12
+ before(:each) do
13
+ @list.subscribe!(@entity)
14
+ end
15
+
16
+ describe "run all delivery" do
17
+ before(:each) do
18
+ @mailing = MailyHerald.one_time_mailing(:test_mailing)
19
+ @mailing.should be_a MailyHerald::OneTimeMailing
20
+ @mailing.should_not be_a_new_record
21
+ end
22
+
23
+ it "should be delivered" do
24
+ subscription = @mailing.subscription_for(@entity)
25
+
26
+ expect(MailyHerald::Subscription.count).to eq(1)
27
+ expect(MailyHerald::Log.delivered.count).to eq(0)
28
+
29
+ subscription.should be_kind_of(MailyHerald::Subscription)
30
+
31
+ @mailing.conditions_met?(@entity).should be_truthy
32
+ @mailing.processable?(@entity).should be_truthy
33
+ @mailing.mailer_name.should eq(:generic)
34
+
35
+ ret = @mailing.run
36
+ ret.should be_a(Array)
37
+ ret.first.should be_a(Mail::Message)
38
+
39
+ MailyHerald::Subscription.count.should eq(1)
40
+ MailyHerald::Log.delivered.count.should eq(1)
41
+
42
+ log = MailyHerald::Log.delivered.first
43
+ log.entity.should eq(@entity)
44
+ log.mailing.should eq(@mailing)
45
+ log.entity_email.should eq(@entity.email)
46
+ end
47
+ end
48
+
49
+ describe "single entity delivery" do
50
+ before(:each) do
51
+ @mailing = MailyHerald.one_time_mailing(:test_mailing)
52
+ @mailing.should be_a MailyHerald::OneTimeMailing
53
+ @mailing.should_not be_a_new_record
54
+ end
55
+
56
+ it "should be delivered" do
57
+ MailyHerald::Log.delivered.count.should eq(0)
58
+ msg = TestMailer.sample_mail(@entity).deliver
59
+ msg.should be_a(Mail::Message)
60
+ MailyHerald::Log.delivered.count.should eq(1)
61
+ end
62
+
63
+ it "should not be delivered if subscription inactive" do
64
+ @list.unsubscribe!(@entity)
65
+ MailyHerald::Log.delivered.count.should eq(0)
66
+ TestMailer.sample_mail(@entity).deliver
67
+ MailyHerald::Log.delivered.count.should eq(0)
68
+ end
69
+ end
70
+
71
+ describe "with entity outside the scope" do
72
+ before(:each) do
73
+ @mailing = MailyHerald.one_time_mailing(:test_mailing)
74
+ end
75
+
76
+ it "should not process mailings" do
77
+ expect(@list.context.scope).to include(@entity)
78
+ expect(@mailing).to be_processable(@entity)
79
+ expect(@mailing).to be_enabled
80
+
81
+ @entity.update_attribute(:active, false)
82
+
83
+ expect(@list.context.scope).not_to include(@entity)
84
+ expect(@list).to be_subscribed(@entity)
85
+
86
+ expect(@mailing).not_to be_processable(@entity)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "with subscription override" do
92
+ before(:each) do
93
+ @mailing = MailyHerald.one_time_mailing(:sample_mail)
94
+ @mailing.update_attribute(:override_subscription, true)
95
+ end
96
+
97
+ after(:each) do
98
+ @mailing.update_attribute(:override_subscription, false)
99
+ end
100
+
101
+ it "single mail should be delivered" do
102
+ MailyHerald::Log.delivered.count.should eq(0)
103
+ @mailing.processable?(@entity).should be_truthy
104
+ @mailing.override_subscription?.should be_truthy
105
+ @mailing.enabled?.should be_truthy
106
+ msg = TestMailer.sample_mail(@entity).deliver
107
+ msg.should be_a(Mail::Message)
108
+ MailyHerald::Log.delivered.count.should eq(1)
109
+ end
110
+ end
111
+
112
+ end
@@ -0,0 +1,339 @@
1
+ require 'spec_helper'
2
+
3
+ describe MailyHerald::PeriodicalMailing do
4
+ before(:each) do
5
+ @mailing = MailyHerald.periodical_mailing(:weekly_summary)
6
+ @mailing.should be_a MailyHerald::PeriodicalMailing
7
+ @mailing.should_not be_a_new_record
8
+
9
+ @list = @mailing.list
10
+ @mailing.start_at.should eq("user.created_at")
11
+ end
12
+
13
+ after do
14
+ Timecop.return
15
+ end
16
+
17
+ describe "Subscribing" do
18
+ before(:each) do
19
+ @entity = FactoryGirl.create :user
20
+ @list.subscribe! @entity
21
+ end
22
+
23
+ it "should create schedule" do
24
+ MailyHerald::Log.scheduled.for_mailing(@mailing).count.should eq(1)
25
+ end
26
+ end
27
+
28
+ describe "Updating schedules" do
29
+ before(:each) do
30
+ @entity = FactoryGirl.create :user
31
+ @list.subscribe! @entity
32
+ @start_at = @mailing.start_at
33
+ end
34
+
35
+ after(:each) do
36
+ @mailing.update_attribute(:start_at, @start_at)
37
+ @mailing.update_attribute(:state, "enabled")
38
+ end
39
+
40
+ it "should be triggered by start_at change" do
41
+ MailyHerald::Log.scheduled.for_mailing(@mailing).count.should eq(1)
42
+ schedule = MailyHerald::Log.scheduled.for_mailing(@mailing).first
43
+ schedule.processing_at.to_i.should eq(@entity.created_at.to_i)
44
+
45
+ time = Time.now + 10.days
46
+ @mailing.update_attribute(:start_at, time.to_s)
47
+
48
+ schedule.reload
49
+ schedule.processing_at.to_i.should eq(time.to_i)
50
+ end
51
+
52
+ it "should be triggered by unsubscribe" do
53
+ MailyHerald::Log.scheduled.for_mailing(@mailing).count.should eq(1)
54
+ schedule = MailyHerald::Log.scheduled.for_mailing(@mailing).first
55
+ schedule.processing_at.to_i.should eq(@entity.created_at.to_i)
56
+
57
+ @list.unsubscribe! @entity
58
+
59
+ expect(MailyHerald::Log.scheduled.for_mailing(@mailing).first).to be_nil
60
+ end
61
+
62
+ it "should be triggered by disabling mailing" do
63
+ MailyHerald::Log.scheduled.for_mailing(@mailing).count.should eq(1)
64
+ schedule = MailyHerald::Log.scheduled.for_mailing(@mailing).first
65
+ schedule.processing_at.to_i.should eq(@entity.created_at.to_i)
66
+
67
+ @mailing.disable!
68
+
69
+ expect(MailyHerald::Log.scheduled.for_mailing(@mailing).first).to be_nil
70
+
71
+ @mailing.enable!
72
+
73
+ expect(MailyHerald::Log.scheduled.for_mailing(@mailing).first).not_to be_nil
74
+
75
+ @mailing.disable!
76
+
77
+ expect(MailyHerald::Log.scheduled.for_mailing(@mailing).first).to be_nil
78
+ end
79
+ end
80
+
81
+ describe "Start time evaluation" do
82
+ before(:each) do
83
+ @entity = FactoryGirl.create :user
84
+ @list.subscribe! @entity
85
+ @start_at = @mailing.start_at
86
+ end
87
+
88
+ after(:each) do
89
+ @mailing.update_attribute(:start_at, @start_at)
90
+ end
91
+
92
+ it "should parse start_at" do
93
+ @entity.should be_a(User)
94
+ @mailing.start_processing_time(@entity).should be_a(Time)
95
+ @mailing.next_processing_time(@entity).should be_a(Time)
96
+ @mailing.next_processing_time(@entity).to_i.should eq(@entity.created_at.to_i)
97
+ end
98
+
99
+ it "should use absolute start date if possible" do
100
+ @entity.should be_a(User)
101
+ time = (@entity.created_at + rand(100).days + rand(24).hours + rand(60).minutes).round
102
+ @mailing.update_attribute(:start_at, time.to_s)
103
+
104
+ @mailing.start_processing_time(@entity).should be_a(Time)
105
+ @mailing.next_processing_time(@entity).should be_a(Time)
106
+ @mailing.next_processing_time(@entity).should eq(time)
107
+ end
108
+ end
109
+
110
+ describe "Periodical Delivery" do
111
+ before(:each) do
112
+ @entity = FactoryGirl.create :user
113
+ @list.subscribe! @entity
114
+ end
115
+
116
+ it "should deliver mailings periodically" do
117
+ @mailing.period.should eq 7.days
118
+
119
+ @mailing.last_processing_time(@entity).should eq nil
120
+ @mailing.next_processing_time(@entity).to_i.should eq((@entity.created_at).to_i)
121
+
122
+ Timecop.freeze @entity.created_at
123
+ @mailing.run
124
+
125
+ @mailing.last_processing_time(@entity).to_i.should eq @entity.created_at.to_i
126
+ @mailing.next_processing_time(@entity).to_i.should eq((@entity.created_at + 7.days).to_i)
127
+ end
128
+
129
+ it "should deliver mailings after period" do
130
+ MailyHerald::Subscription.count.should eq(1)
131
+ MailyHerald::Log.processed.count.should eq(0)
132
+
133
+ Timecop.freeze @entity.created_at
134
+
135
+ @mailing.conditions_met?(@entity).should be_truthy
136
+ @mailing.processable?(@entity).should be_truthy
137
+ @mailing.next_processing_time(@entity).should be <= @entity.created_at
138
+
139
+ @mailing.logs(@entity).scheduled.count.should eq(1)
140
+ schedule = @mailing.logs(@entity).scheduled.first
141
+
142
+ @mailing.run
143
+
144
+ schedule.reload
145
+ schedule.status.should eq(:delivered)
146
+
147
+ MailyHerald::Subscription.count.should eq(1)
148
+ MailyHerald::Log.processed.count.should eq(1)
149
+
150
+ log = MailyHerald::Log.processed.first
151
+ log.entity.should eq(@entity)
152
+ log.entity_email.should eq(@entity.email)
153
+ log.mailing.should eq(@mailing)
154
+
155
+ @mailing.logs(@entity).processed.last.should eq(log)
156
+ @mailing.last_processing_time(@entity).to_i.should eq(@entity.created_at.to_i)
157
+
158
+ @mailing.logs(@entity).scheduled.count.should eq(1)
159
+
160
+ @mailing.run
161
+
162
+ MailyHerald::Subscription.count.should eq(1)
163
+ MailyHerald::Log.processed.count.should eq(1)
164
+
165
+ Timecop.freeze @entity.created_at + @mailing.period + @mailing.period/3
166
+
167
+ @mailing.logs(@entity).scheduled.count.should eq(1)
168
+
169
+ @mailing.run
170
+
171
+ MailyHerald::Subscription.count.should eq(1)
172
+ MailyHerald::Log.processed.count.should eq(2)
173
+
174
+ Timecop.freeze @entity.created_at + @mailing.period + @mailing.period/2
175
+
176
+ @mailing.run
177
+
178
+ MailyHerald::Subscription.count.should eq(1)
179
+ MailyHerald::Log.processed.count.should eq(2)
180
+ end
181
+
182
+ it "should calculate valid next delivery date" do
183
+ period = @mailing.period
184
+
185
+ @mailing.last_processing_time(@entity).should be_nil
186
+ @mailing.start_processing_time(@entity).should be_a(Time)
187
+ @mailing.start_processing_time(@entity).should eq(@entity.created_at)
188
+ @mailing.next_processing_time(@entity).to_i.should eq(@entity.created_at.to_i)
189
+ end
190
+
191
+ it "should handle processing with start date evaluated to the past date" do
192
+ MailyHerald::Subscription.count.should eq(1)
193
+ MailyHerald::Log.processed.count.should eq(0)
194
+
195
+ @mailing.next_processing_time(@entity).to_i.should eq(@entity.created_at.to_i)
196
+ start_at = @entity.created_at + 1.year
197
+
198
+ Timecop.freeze start_at
199
+
200
+ @mailing.conditions_met?(@entity).should be_truthy
201
+ @mailing.processable?(@entity).should be_truthy
202
+
203
+ @mailing.run
204
+
205
+ MailyHerald::Subscription.count.should eq(1)
206
+ MailyHerald::Log.processed.count.should eq(1)
207
+ @mailing.last_processing_time(@entity).to_i.should eq(start_at.to_i)
208
+
209
+ Timecop.freeze start_at +1
210
+ @mailing.run
211
+
212
+ MailyHerald::Subscription.count.should eq(1)
213
+ MailyHerald::Log.delivered.count.should eq(1)
214
+
215
+ @mailing.next_processing_time(@entity).to_i.should eq((start_at + @mailing.period).to_i)
216
+ Timecop.freeze start_at + @mailing.period
217
+
218
+ @mailing.run
219
+
220
+ MailyHerald::Subscription.count.should eq(1)
221
+ MailyHerald::Log.delivered.count.should eq(2)
222
+ end
223
+ end
224
+
225
+ pending "Error handling" do
226
+ before do
227
+ @old_start_at = @mailing.start_at
228
+ @mailing.update_attribute(:start_at, "")
229
+ end
230
+
231
+ before(:each) do
232
+ @entity = FactoryGirl.create :user
233
+ @list.subscribe! @entity
234
+ end
235
+
236
+ it "should handle start_at parsing errors or nil start time" do
237
+ @mailing.last_processing_time(@entity).should be_nil
238
+ @mailing.next_processing_time(@entity).should be_nil
239
+
240
+ Timecop.freeze @entity.created_at
241
+ @mailing.run
242
+
243
+ @mailing.last_processing_time(@entity).should be_nil
244
+ @mailing.next_processing_time(@entity).should be_nil
245
+ end
246
+
247
+ after do
248
+ @mailing.update_attribute(:start_at, @old_start_at)
249
+ end
250
+ end
251
+
252
+ describe "Without subscription" do
253
+ before(:each) do
254
+ @entity = FactoryGirl.create :user
255
+ end
256
+
257
+ after(:each) do
258
+ @mailing.update_attribute(:override_subscription, false)
259
+ end
260
+
261
+ it "should not deliver" do
262
+ MailyHerald::Subscription.count.should eq(0)
263
+ MailyHerald::Log.count.should eq(0)
264
+
265
+ Timecop.freeze @entity.created_at
266
+
267
+ @mailing.run
268
+
269
+ MailyHerald::Subscription.count.should eq(0)
270
+ MailyHerald::Log.count.should eq(0)
271
+ end
272
+
273
+ it "should not deliver individual mailing" do
274
+ MailyHerald::Subscription.count.should eq(0)
275
+ MailyHerald::Log.count.should eq(0)
276
+
277
+ Timecop.freeze @entity.created_at
278
+
279
+ @mailing.deliver_to @entity
280
+
281
+ MailyHerald::Subscription.count.should eq(0)
282
+ MailyHerald::Log.count.should eq(0)
283
+ end
284
+
285
+ it "should deliver with subscription override" do
286
+ MailyHerald::Subscription.count.should eq(0)
287
+ MailyHerald::Log.count.should eq(0)
288
+
289
+ @mailing.update_attribute(:override_subscription, true)
290
+ MailyHerald::Log.scheduled.count.should eq(1)
291
+
292
+ Timecop.freeze @entity.created_at
293
+
294
+ @mailing.run
295
+
296
+ MailyHerald::Subscription.count.should eq(0)
297
+ MailyHerald::Log.delivered.count.should eq(1)
298
+ end
299
+ end
300
+
301
+ describe "Conditions" do
302
+ before(:each) do
303
+ @entity = FactoryGirl.create :user
304
+ @list.subscribe! @entity
305
+ end
306
+
307
+ it "should check mailing conditions" do
308
+ MailyHerald::Subscription.count.should eq(1)
309
+ MailyHerald::Log.delivered.count.should eq(0)
310
+
311
+ Timecop.freeze @entity.created_at
312
+
313
+ @mailing.run
314
+
315
+ MailyHerald::Subscription.count.should eq(1)
316
+ MailyHerald::Log.delivered.count.should eq(1)
317
+
318
+ @entity.update_attribute(:weekly_notifications, false)
319
+ @entity.save
320
+
321
+ Timecop.freeze @entity.created_at + @mailing.period + @mailing.period/3
322
+
323
+ @mailing.run
324
+
325
+ MailyHerald::Subscription.count.should eq(1)
326
+ MailyHerald::Log.delivered.count.should eq(1)
327
+ MailyHerald::Log.skipped.count.should eq(1)
328
+
329
+ @entity.update_attribute(:weekly_notifications, true)
330
+
331
+ Timecop.freeze @entity.created_at + @mailing.period*2 + @mailing.period/3
332
+
333
+ @mailing.run
334
+
335
+ MailyHerald::Subscription.count.should eq(1)
336
+ MailyHerald::Log.delivered.count.should eq(2)
337
+ end
338
+ end
339
+ end