activity_notification 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +41 -3
  4. data/app/jobs/activity_notification/notify_all_job.rb +9 -0
  5. data/app/jobs/activity_notification/notify_job.rb +9 -0
  6. data/app/jobs/activity_notification/notify_to_job.rb +9 -0
  7. data/lib/activity_notification/apis/notification_api.rb +114 -18
  8. data/lib/activity_notification/config.rb +20 -0
  9. data/lib/activity_notification/models/concerns/notifiable.rb +63 -0
  10. data/lib/activity_notification/models/concerns/target.rb +23 -2
  11. data/lib/activity_notification/roles/acts_as_notifiable.rb +8 -0
  12. data/lib/activity_notification/version.rb +1 -1
  13. data/lib/generators/templates/activity_notification.rb +6 -0
  14. data/lib/generators/templates/migrations/migration.rb +5 -5
  15. data/spec/concerns/apis/notification_api_spec.rb +107 -0
  16. data/spec/concerns/models/notifiable_spec.rb +25 -4
  17. data/spec/concerns/models/subscriber_spec.rb +11 -11
  18. data/spec/concerns/models/target_spec.rb +9 -2
  19. data/spec/generators/migration/migration_generator_spec.rb +37 -4
  20. data/spec/jobs/notify_all_job_spec.rb +23 -0
  21. data/spec/jobs/notify_job_spec.rb +23 -0
  22. data/spec/jobs/notify_to_job_spec.rb +23 -0
  23. data/spec/rails_app/app/controllers/comments_controller.rb +4 -1
  24. data/spec/rails_app/app/models/dummy/dummy_base.rb +1 -0
  25. data/spec/rails_app/app/models/dummy/dummy_group.rb +1 -0
  26. data/spec/rails_app/app/models/dummy/dummy_notifiable.rb +1 -0
  27. data/spec/rails_app/app/models/dummy/dummy_notifiable_target.rb +1 -0
  28. data/spec/rails_app/app/models/dummy/dummy_notifier.rb +1 -0
  29. data/spec/rails_app/app/models/dummy/dummy_subscriber.rb +1 -0
  30. data/spec/rails_app/app/models/dummy/dummy_target.rb +1 -0
  31. data/spec/rails_app/config/initializers/activity_notification.rb +6 -0
  32. data/spec/rails_app/db/migrate/{20160715050433_create_test_tables.rb → 20160716000000_create_test_tables.rb} +1 -1
  33. data/spec/rails_app/db/migrate/{20160715050420_create_activity_notification_tables.rb → 20181209000000_create_activity_notification_tables.rb} +3 -3
  34. data/spec/rails_app/db/schema.rb +43 -43
  35. data/spec/roles/acts_as_notifiable_spec.rb +45 -0
  36. metadata +15 -6
@@ -115,6 +115,8 @@ module ActivityNotification
115
115
  # Tracked notifications are disabled as default.
116
116
  # When you set true as this :tracked option, default callbacks will be enabled for [:create, :update].
117
117
  # You can use :only, :except and other notify options as hash for this option.
118
+ # Tracked notifications are generated synchronously as default configuration.
119
+ # You can use :notify_later option as notify options to make tracked notifications generated asynchronously.
118
120
  # @example Add all callbacks to generate notifications for creation and update
119
121
  # # app/models/comment.rb
120
122
  # class Comment < ActiveRecord::Base
@@ -133,6 +135,12 @@ module ActivityNotification
133
135
  # belongs_to :article
134
136
  # acts_as_notifiable :users, targets: User.all, tracked: { except: [:update], key: "comment.edited", send_later: false }
135
137
  # end
138
+ # @example Add callbacks to generate notifications asynchronously for creation only
139
+ # # app/models/comment.rb
140
+ # class Comment < ActiveRecord::Base
141
+ # belongs_to :article
142
+ # acts_as_notifiable :users, targets: User.all, tracked: { only: [:create], notify_later: true }
143
+ # end
136
144
  #
137
145
  # * :printable_name or :printable_notifiable_name
138
146
  # * Printable notifiable name.
@@ -1,3 +1,3 @@
1
1
  module ActivityNotification
2
- VERSION = "1.6.1"
2
+ VERSION = "1.7.0"
3
3
  end
@@ -41,6 +41,9 @@ ActivityNotification.configure do |config|
41
41
  # Configure the parent class responsible to send e-mails.
42
42
  # config.parent_mailer = 'ActionMailer::Base'
43
43
 
44
+ # Configure the parent job class for delayed notifications.
45
+ # config.parent_job = 'ActiveJob::Base'
46
+
44
47
  # Configure the parent class for activity_notification controllers.
45
48
  # config.parent_controller = 'ApplicationController'
46
49
 
@@ -50,4 +53,7 @@ ActivityNotification.configure do |config|
50
53
  # Configure default limit number of opened notifications you can get from opened* scope
51
54
  config.opened_index_limit = 10
52
55
 
56
+ # Configure ActiveJob queue name for delayed notifications.
57
+ config.active_job_queue = :activity_notification
58
+
53
59
  end
@@ -1,5 +1,5 @@
1
1
  # Migration responsible for creating a table with notifications
2
- class <%= @migration_name %> < ActiveRecord::Migration
2
+ class <%= @migration_name %> < ActiveRecord::Migration<%= Rails::VERSION::MAJOR >= 5 ? "[#{Rails.version.to_f}]" : "" %>
3
3
  # Create tables
4
4
  def change
5
5
  <% if @migration_tables.include?('notifications') %>create_table :notifications do |t|
@@ -12,7 +12,7 @@ class <%= @migration_name %> < ActiveRecord::Migration
12
12
  t.text :parameters
13
13
  t.datetime :opened_at
14
14
 
15
- t.timestamps
15
+ t.timestamps null: false
16
16
  end<% else %># create_table :notifications do |t|
17
17
  # t.belongs_to :target, polymorphic: true, index: true, null: false
18
18
  # t.belongs_to :notifiable, polymorphic: true, index: true, null: false
@@ -23,7 +23,7 @@ class <%= @migration_name %> < ActiveRecord::Migration
23
23
  # t.text :parameters
24
24
  # t.datetime :opened_at
25
25
  #
26
- # t.timestamps
26
+ # t.timestamps null: false
27
27
  # end<% end %>
28
28
 
29
29
  <% if @migration_tables.include?('subscriptions') %>create_table :subscriptions do |t|
@@ -37,7 +37,7 @@ class <%= @migration_name %> < ActiveRecord::Migration
37
37
  t.datetime :unsubscribed_to_email_at
38
38
  t.text :optional_targets
39
39
 
40
- t.timestamps
40
+ t.timestamps null: false
41
41
  end
42
42
  add_index :subscriptions, [:target_type, :target_id, :key], unique: true<% else %># create_table :subscriptions do |t|
43
43
  # t.belongs_to :target, polymorphic: true, index: true, null: false
@@ -50,7 +50,7 @@ class <%= @migration_name %> < ActiveRecord::Migration
50
50
  # t.datetime :unsubscribed_to_email_at
51
51
  # t.text :optional_targets
52
52
  #
53
- # t.timestamps
53
+ # t.timestamps null: false
54
54
  # end
55
55
  # add_index :subscriptions, [:target_type, :target_id, :key], unique: true<% end %>
56
56
  end
@@ -62,6 +62,23 @@ shared_examples_for :notification_api do
62
62
  end
63
63
  end
64
64
 
65
+ context "with notify_later true" do
66
+ it "generates notifications later" do
67
+ expect {
68
+ described_class.notify(:users, @comment_2, notify_later: true)
69
+ }.to have_enqueued_job(ActivityNotification::NotifyJob)
70
+ end
71
+
72
+ it "creates notification records later" do
73
+ perform_enqueued_jobs do
74
+ described_class.notify(:users, @comment_2, notify_later: true)
75
+ end
76
+ expect(@author_user.notifications.unopened_only.count).to eq(1)
77
+ expect(@user_1.notifications.unopened_only.count).to eq(1)
78
+ expect(@user_2.notifications.unopened_only.count).to eq(0)
79
+ end
80
+ end
81
+
65
82
  context "with send_later false" do
66
83
  it "sends notification email now" do
67
84
  described_class.notify(:users, @comment_2, send_later: false)
@@ -72,6 +89,14 @@ shared_examples_for :notification_api do
72
89
  end
73
90
 
74
91
  context "with pass_full_options" do
92
+ before do
93
+ @original_targets = Comment._notification_targets[:users]
94
+ end
95
+
96
+ after do
97
+ Comment._notification_targets[:users] = @original_targets
98
+ end
99
+
75
100
  context "as false (as default)" do
76
101
  it "accepts specified lambda with notifiable and key arguments" do
77
102
  Comment._notification_targets[:users] = ->(notifiable, key){ User.all if key == 'dummy_key' }
@@ -98,7 +123,23 @@ shared_examples_for :notification_api do
98
123
  end
99
124
  end
100
125
  end
126
+ end
101
127
 
128
+ describe ".notify_later" do
129
+ it "generates notifications later" do
130
+ expect {
131
+ described_class.notify_later(:users, @comment_2)
132
+ }.to have_enqueued_job(ActivityNotification::NotifyJob)
133
+ end
134
+
135
+ it "creates notification records later" do
136
+ perform_enqueued_jobs do
137
+ described_class.notify_later(:users, @comment_2)
138
+ end
139
+ expect(@author_user.notifications.unopened_only.count).to eq(1)
140
+ expect(@user_1.notifications.unopened_only.count).to eq(1)
141
+ expect(@user_2.notifications.unopened_only.count).to eq(0)
142
+ end
102
143
  end
103
144
 
104
145
  describe ".notify_all" do
@@ -136,6 +177,23 @@ shared_examples_for :notification_api do
136
177
  end
137
178
  end
138
179
 
180
+ context "with notify_later true" do
181
+ it "generates notifications later" do
182
+ expect {
183
+ described_class.notify_all([@author_user, @user_1], @comment_2, notify_later: true)
184
+ }.to have_enqueued_job(ActivityNotification::NotifyAllJob)
185
+ end
186
+
187
+ it "creates notification records later" do
188
+ perform_enqueued_jobs do
189
+ described_class.notify_all([@author_user, @user_1], @comment_2, notify_later: true)
190
+ end
191
+ expect(@author_user.notifications.unopened_only.count).to eq(1)
192
+ expect(@user_1.notifications.unopened_only.count).to eq(1)
193
+ expect(@user_2.notifications.unopened_only.count).to eq(0)
194
+ end
195
+ end
196
+
139
197
  context "with send_later false" do
140
198
  it "sends notification email now" do
141
199
  described_class.notify_all([@author_user, @user_1], @comment_2, send_later: false)
@@ -146,6 +204,23 @@ shared_examples_for :notification_api do
146
204
  end
147
205
  end
148
206
 
207
+ describe ".notify_all_later" do
208
+ it "generates notifications later" do
209
+ expect {
210
+ described_class.notify_all_later([@author_user, @user_1], @comment_2)
211
+ }.to have_enqueued_job(ActivityNotification::NotifyAllJob)
212
+ end
213
+
214
+ it "creates notification records later" do
215
+ perform_enqueued_jobs do
216
+ described_class.notify_all_later([@author_user, @user_1], @comment_2)
217
+ end
218
+ expect(@author_user.notifications.unopened_only.count).to eq(1)
219
+ expect(@user_1.notifications.unopened_only.count).to eq(1)
220
+ expect(@user_2.notifications.unopened_only.count).to eq(0)
221
+ end
222
+ end
223
+
149
224
  describe ".notify_to" do
150
225
  it "returns created notification" do
151
226
  notification = described_class.notify_to(@user_1, @comment_2)
@@ -176,6 +251,22 @@ shared_examples_for :notification_api do
176
251
  end
177
252
  end
178
253
 
254
+ context "with notify_later true" do
255
+ it "generates notifications later" do
256
+ expect {
257
+ described_class.notify_to(@user_1, @comment_2, notify_later: true)
258
+ }.to have_enqueued_job(ActivityNotification::NotifyToJob)
259
+ end
260
+
261
+ it "creates notification records later" do
262
+ perform_enqueued_jobs do
263
+ described_class.notify_to(@user_1, @comment_2, notify_later: true)
264
+ end
265
+ expect(@user_1.notifications.unopened_only.count).to eq(1)
266
+ expect(@user_2.notifications.unopened_only.count).to eq(0)
267
+ end
268
+ end
269
+
179
270
  context "with send_later false" do
180
271
  it "sends notification email now" do
181
272
  described_class.notify_to(@user_1, @comment_2, send_later: false)
@@ -355,6 +446,22 @@ shared_examples_for :notification_api do
355
446
  end
356
447
  end
357
448
 
449
+ describe ".notify_later_to" do
450
+ it "generates notifications later" do
451
+ expect {
452
+ described_class.notify_later_to(@user_1, @comment_2)
453
+ }.to have_enqueued_job(ActivityNotification::NotifyToJob)
454
+ end
455
+
456
+ it "creates notification records later" do
457
+ perform_enqueued_jobs do
458
+ described_class.notify_later_to(@user_1, @comment_2)
459
+ end
460
+ expect(@user_1.notifications.unopened_only.count).to eq(1)
461
+ expect(@user_2.notifications.unopened_only.count).to eq(0)
462
+ end
463
+ end
464
+
358
465
  describe ".open_all_of" do
359
466
  before do
360
467
  described_class.notify_to(@user_1, @article, group: @article, key: 'key.1')
@@ -607,10 +607,10 @@ shared_examples_for :notifiable do
607
607
  end
608
608
  end
609
609
 
610
- describe "#notify_to" do
611
- it "is an alias of ActivityNotification::Notification.notify_to" do
612
- expect(ActivityNotification::Notification).to receive(:notify_to)
613
- test_instance.notify_to create(:user)
610
+ describe "#notify_later" do
611
+ it "is an alias of ActivityNotification::Notification.notify_later" do
612
+ expect(ActivityNotification::Notification).to receive(:notify_later)
613
+ test_instance.notify_later :users
614
614
  end
615
615
  end
616
616
 
@@ -621,6 +621,27 @@ shared_examples_for :notifiable do
621
621
  end
622
622
  end
623
623
 
624
+ describe "#notify_all_later" do
625
+ it "is an alias of ActivityNotification::Notification.notify_all_later" do
626
+ expect(ActivityNotification::Notification).to receive(:notify_all_later)
627
+ test_instance.notify_all_later [create(:user)]
628
+ end
629
+ end
630
+
631
+ describe "#notify_to" do
632
+ it "is an alias of ActivityNotification::Notification.notify_to" do
633
+ expect(ActivityNotification::Notification).to receive(:notify_to)
634
+ test_instance.notify_to create(:user)
635
+ end
636
+ end
637
+
638
+ describe "#notify_later_to" do
639
+ it "is an alias of ActivityNotification::Notification.notify_later_to" do
640
+ expect(ActivityNotification::Notification).to receive(:notify_later_to)
641
+ test_instance.notify_later_to create(:user)
642
+ end
643
+ end
644
+
624
645
  describe "#default_notification_key" do
625
646
  it "returns '#to_resource_name.default'" do
626
647
  expect(test_instance.default_notification_key).to eq("#{test_instance.to_resource_name}.default")
@@ -338,7 +338,7 @@ shared_examples_for :subscriber do
338
338
 
339
339
  # Function test for subscriptions
340
340
 
341
- describe "#notify_to" do
341
+ describe "#receive_notification_of" do
342
342
  before do
343
343
  @test_key = 'test_key'
344
344
  Comment.acts_as_notifiable described_class.to_s.underscore.pluralize.to_sym, targets: [], email_allowed: true
@@ -353,13 +353,13 @@ shared_examples_for :subscriber do
353
353
  end
354
354
 
355
355
  it "returns created notification" do
356
- notification = test_instance.notify_to(@notifiable, key: @test_key)
356
+ notification = test_instance.receive_notification_of(@notifiable, key: @test_key)
357
357
  expect(notification).not_to be_nil
358
358
  expect(notification.target).to eq(test_instance)
359
359
  end
360
360
 
361
361
  it "creates notification records" do
362
- test_instance.notify_to(@notifiable, key: @test_key)
362
+ test_instance.receive_notification_of(@notifiable, key: @test_key)
363
363
  expect(test_instance.notifications.unopened_only.count).to eq(1)
364
364
  end
365
365
  end
@@ -374,7 +374,7 @@ shared_examples_for :subscriber do
374
374
  it "sends notification email later" do
375
375
  expect {
376
376
  perform_enqueued_jobs do
377
- test_instance.notify_to(@notifiable, key: @test_key)
377
+ test_instance.receive_notification_of(@notifiable, key: @test_key)
378
378
  end
379
379
  }.to change { ActivityNotification::Mailer.deliveries.size }.by(1)
380
380
  expect(ActivityNotification::Mailer.deliveries.size).to eq(1)
@@ -382,14 +382,14 @@ shared_examples_for :subscriber do
382
382
 
383
383
  it "sends notification email with active job queue" do
384
384
  expect {
385
- test_instance.notify_to(@notifiable, key: @test_key)
385
+ test_instance.receive_notification_of(@notifiable, key: @test_key)
386
386
  }.to change(ActiveJob::Base.queue_adapter.enqueued_jobs, :size).by(1)
387
387
  end
388
388
  end
389
389
 
390
390
  context "with send_later false" do
391
391
  it "sends notification email now" do
392
- test_instance.notify_to(@notifiable, key: @test_key, send_later: false)
392
+ test_instance.receive_notification_of(@notifiable, key: @test_key, send_later: false)
393
393
  expect(ActivityNotification::Mailer.deliveries.size).to eq(1)
394
394
  end
395
395
  end
@@ -402,12 +402,12 @@ shared_examples_for :subscriber do
402
402
  end
403
403
 
404
404
  it "returns nil" do
405
- notification = test_instance.notify_to(@notifiable, key: @test_key)
405
+ notification = test_instance.receive_notification_of(@notifiable, key: @test_key)
406
406
  expect(notification).to be_nil
407
407
  end
408
408
 
409
409
  it "does not create notification records" do
410
- test_instance.notify_to(@notifiable, key: @test_key)
410
+ test_instance.receive_notification_of(@notifiable, key: @test_key)
411
411
  expect(test_instance.notifications.unopened_only.count).to eq(0)
412
412
  end
413
413
  end
@@ -422,7 +422,7 @@ shared_examples_for :subscriber do
422
422
  it "does not send notification email later" do
423
423
  expect {
424
424
  perform_enqueued_jobs do
425
- test_instance.notify_to(@notifiable, key: @test_key)
425
+ test_instance.receive_notification_of(@notifiable, key: @test_key)
426
426
  end
427
427
  }.to change { ActivityNotification::Mailer.deliveries.size }.by(0)
428
428
  expect(ActivityNotification::Mailer.deliveries.size).to eq(0)
@@ -430,14 +430,14 @@ shared_examples_for :subscriber do
430
430
 
431
431
  it "does not send notification email with active job queue" do
432
432
  expect {
433
- test_instance.notify_to(@notifiable, key: @test_key)
433
+ test_instance.receive_notification_of(@notifiable, key: @test_key)
434
434
  }.to change(ActiveJob::Base.queue_adapter.enqueued_jobs, :size).by(0)
435
435
  end
436
436
  end
437
437
 
438
438
  context "with send_later false" do
439
439
  it "does not send notification email now" do
440
- test_instance.notify_to(@notifiable, key: @test_key, send_later: false)
440
+ test_instance.receive_notification_of(@notifiable, key: @test_key, send_later: false)
441
441
  expect(ActivityNotification::Mailer.deliveries.size).to eq(0)
442
442
  end
443
443
  end
@@ -778,10 +778,17 @@ shared_examples_for :target do
778
778
 
779
779
  # Wrapper methods of Notification class methods
780
780
 
781
- describe "#notify_to" do
781
+ describe "#receive_notification_of" do
782
782
  it "is an alias of ActivityNotification::Notification.notify_to" do
783
783
  expect(ActivityNotification::Notification).to receive(:notify_to)
784
- test_instance.notify_to create(:user)
784
+ test_instance.receive_notification_of create(:user)
785
+ end
786
+ end
787
+
788
+ describe "#receive_notification_later_of" do
789
+ it "is an alias of ActivityNotification::Notification.notify_later_to" do
790
+ expect(ActivityNotification::Notification).to receive(:notify_later_to)
791
+ test_instance.receive_notification_later_of create(:user)
785
792
  end
786
793
  end
787
794
 
@@ -4,7 +4,17 @@ describe ActivityNotification::Generators::MigrationGenerator, type: :generator
4
4
 
5
5
  # setup_default_destination
6
6
  destination File.expand_path("../../../../tmp", __FILE__)
7
- before { prepare_destination }
7
+
8
+ before do
9
+ prepare_destination
10
+ end
11
+
12
+ after do
13
+ if ActivityNotification.config.orm == :active_record
14
+ ActivityNotification::Notification.reset_column_information
15
+ ActivityNotification::Subscription.reset_column_information
16
+ end
17
+ end
8
18
 
9
19
  it 'runs generating migration tasks' do
10
20
  gen = generator
@@ -21,7 +31,19 @@ describe ActivityNotification::Generators::MigrationGenerator, type: :generator
21
31
  describe 'CreateNotifications migration file' do
22
32
  subject { file(Dir["tmp/db/migrate/*_create_activity_notification_tables.rb"].first.gsub!('tmp/', '')) }
23
33
  it { is_expected.to exist }
24
- it { is_expected.to contain(/class CreateActivityNotificationTables < ActiveRecord::Migration/) }
34
+ if Rails::VERSION::MAJOR >= 5
35
+ it { is_expected.to contain(/class CreateActivityNotificationTables < ActiveRecord::Migration\[\d\.\d\]/) }
36
+ else
37
+ it { is_expected.to contain(/class CreateActivityNotificationTables < ActiveRecord::Migration/) }
38
+ end
39
+
40
+ if ActivityNotification.config.orm == :active_record
41
+ it 'can be executed to migrate scheme' do
42
+ require subject
43
+ CreateActivityNotificationTables.new.migrate(:down)
44
+ CreateActivityNotificationTables.new.migrate(:up)
45
+ end
46
+ end
25
47
  end
26
48
  end
27
49
 
@@ -33,9 +55,20 @@ describe ActivityNotification::Generators::MigrationGenerator, type: :generator
33
55
  describe 'CreateCustomNotifications migration file' do
34
56
  subject { file(Dir["tmp/db/migrate/*_create_custom_notifications.rb"].first.gsub!('tmp/', '')) }
35
57
  it { is_expected.to exist }
36
- it { is_expected.to contain(/class CreateCustomNotifications < ActiveRecord::Migration/) }
58
+ if Rails::VERSION::MAJOR >= 5
59
+ it { is_expected.to contain(/class CreateCustomNotifications < ActiveRecord::Migration\[\d\.\d\]/) }
60
+ else
61
+ it { is_expected.to contain(/class CreateCustomNotifications < ActiveRecord::Migration/) }
62
+ end
63
+
64
+ if ActivityNotification.config.orm == :active_record
65
+ it 'can be executed to migrate scheme' do
66
+ require subject
67
+ CreateActivityNotificationTables.new.migrate(:down)
68
+ CreateActivityNotificationTables.new.migrate(:up)
69
+ end
70
+ end
37
71
  end
38
72
  end
39
-
40
73
  end
41
74
  end