activity_notification 1.6.1 → 1.7.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.
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