active_delivery 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +53 -21
- data/lib/.rbnext/3.0/abstract_notifier/async_adapters/active_job.rb +2 -2
- data/lib/.rbnext/3.0/abstract_notifier/base.rb +4 -4
- data/lib/.rbnext/3.0/active_delivery/base.rb +8 -8
- data/lib/.rbnext/3.0/active_delivery/lines/base.rb +4 -4
- data/lib/.rbnext/3.0/active_delivery/testing/minitest.rb +58 -0
- data/lib/.rbnext/3.0/active_delivery/testing.rb +1 -0
- data/lib/.rbnext/3.1/abstract_notifier/async_adapters/active_job.rb +2 -2
- data/lib/.rbnext/3.1/abstract_notifier/base.rb +4 -4
- data/lib/.rbnext/3.1/active_delivery/base.rb +8 -8
- data/lib/.rbnext/3.1/active_delivery/lines/base.rb +4 -4
- data/lib/.rbnext/3.1/active_delivery/testing/minitest.rb +58 -0
- data/lib/.rbnext/3.2/abstract_notifier/async_adapters/active_job.rb +36 -0
- data/lib/.rbnext/3.2/abstract_notifier/base.rb +223 -0
- data/lib/.rbnext/3.2/abstract_notifier/testing/rspec.rb +164 -0
- data/lib/.rbnext/3.2/abstract_notifier/testing.rb +53 -0
- data/lib/.rbnext/3.2/active_delivery/base.rb +249 -0
- data/lib/.rbnext/3.2/active_delivery/lines/base.rb +101 -0
- data/lib/.rbnext/3.2/active_delivery/lines/notifier.rb +57 -0
- data/lib/.rbnext/3.2/active_delivery/testing/rspec.rb +222 -0
- data/lib/abstract_notifier/async_adapters/active_job.rb +2 -2
- data/lib/abstract_notifier/base.rb +4 -4
- data/lib/abstract_notifier/testing/minitest.rb +1 -1
- data/lib/abstract_notifier/testing/rspec.rb +4 -4
- data/lib/abstract_notifier/testing.rb +2 -2
- data/lib/active_delivery/base.rb +8 -8
- data/lib/active_delivery/lines/base.rb +4 -4
- data/lib/active_delivery/lines/notifier.rb +6 -6
- data/lib/active_delivery/testing/minitest.rb +58 -0
- data/lib/active_delivery/testing/rspec.rb +4 -4
- data/lib/active_delivery/testing.rb +1 -0
- data/lib/active_delivery/version.rb +1 -1
- metadata +17 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d05087cb016af8444f7668b81681675248b7b63f41f77a1d9fdb22b65ccb6845
|
4
|
+
data.tar.gz: d60851ccb9d9ea6557d131289942edf57b39c79a499e37d41f8f1d06b480446f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a94a2fd3e2f19d9e99c0df6494752b23649802b064b390ea50d65506b01beb57650f31f5cd140495d6befa847a65423cc141ec8c313a6a116de69a4cd5576df
|
7
|
+
data.tar.gz: 4febe7f49e314d27f370642fa43085c5020dae8bac7fa9a3512514a6b861d17b726d4685ed91f081eab22f4c2af68a4117d37f8f29a576c78fe323f2c73b58e2
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 1.2.0 (2024-02-05)
|
6
|
+
|
7
|
+
- Add Minitest assertions (`assert_deliveries`, `assert_no_deliveries`, `assert_delivery_enqueued`). ([@palkan][])
|
8
|
+
|
5
9
|
## 1.1.0 (2023-12-01) ❄️
|
6
10
|
|
7
11
|
- Support delayed delivery options (e.g, `wait_until`). ([@palkan][])
|
data/README.md
CHANGED
@@ -10,6 +10,8 @@ Since v1.0, Active Delivery is bundled with [Abstract Notifier](https://github.c
|
|
10
10
|
|
11
11
|
📖 Read the introduction post: ["Crafting user notifications in Rails with Active Delivery"](https://evilmartians.com/chronicles/crafting-user-notifications-in-rails-with-active-delivery)
|
12
12
|
|
13
|
+
📖 Read more about designing notifications layer in Ruby on Rails applications in the [Layered design for Ruby on Rails applications](https://www.packtpub.com/product/layered-design-for-ruby-on-rails-applications/9781801813785) book.
|
14
|
+
|
13
15
|
<a href="https://evilmartians.com/?utm_source=action_policy">
|
14
16
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
15
17
|
|
@@ -56,7 +58,7 @@ end
|
|
56
58
|
Add this line to your application's Gemfile:
|
57
59
|
|
58
60
|
```ruby
|
59
|
-
gem "active_delivery", "1.0
|
61
|
+
gem "active_delivery", "~> 1.0"
|
60
62
|
```
|
61
63
|
|
62
64
|
And then execute:
|
@@ -291,17 +293,36 @@ MyDeliver.notify(:something_wicked_this_way_comes)
|
|
291
293
|
|
292
294
|
## Testing
|
293
295
|
|
294
|
-
|
296
|
+
### Setup
|
297
|
+
|
298
|
+
Test mode is activated automatically if `RAILS_ENV` or `RACK_ENV` env variable is equal to "test". Otherwise, add `require "active_delivery/testing/rspec"` to your `spec_helper.rb` / `rails_helper.rb` manually or `require "active_delivery/testing/minitest"`. This is also required if you're using Spring in the test environment (e.g. with help of [spring-commands-rspec](https://github.com/jonleighton/spring-commands-rspec)).
|
299
|
+
|
300
|
+
For Minitest, you also MUST include the test helper into your test class. For example:
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
class ActiveSupport::TestCase
|
304
|
+
# ...
|
305
|
+
include ActiveDelivery::TestHelper
|
306
|
+
end
|
307
|
+
```
|
295
308
|
|
296
309
|
### Deliveries
|
297
310
|
|
298
|
-
Active Delivery provides an elegant way to test deliveries in your code (i.e., when you want to check whether a notification has been sent) through a `have_delivered_to` matcher:
|
311
|
+
Active Delivery provides an elegant way to test deliveries in your code (i.e., when you want to check whether a notification has been sent) through a `have_delivered_to` RSpec matcher or `assert_delivery_enqueued` Minitest assertion:
|
299
312
|
|
300
313
|
```ruby
|
314
|
+
# RSpec
|
301
315
|
it "delivers notification" do
|
302
316
|
expect { subject }.to have_delivered_to(Community::EventsDelivery, :modified, event)
|
303
317
|
.with(profile: profile)
|
304
318
|
end
|
319
|
+
|
320
|
+
# Minitest
|
321
|
+
def test_delivers_notification
|
322
|
+
assert_delivery_enqueued(Community::EventsDelivery, :modified, with: [event]) do
|
323
|
+
some_action
|
324
|
+
end
|
325
|
+
end
|
305
326
|
```
|
306
327
|
|
307
328
|
You can also use such RSpec features as compound expectations and composed matchers:
|
@@ -320,14 +341,27 @@ end
|
|
320
341
|
If you want to test that no notification is delivered you can use negation
|
321
342
|
|
322
343
|
```ruby
|
344
|
+
# RSpec
|
323
345
|
specify "when event is not found" do
|
324
346
|
expect do
|
325
347
|
described_class.perform_now(profile.id, "123", "one_hour_before")
|
326
348
|
end.not_to have_delivered_to(Community::EventsDelivery)
|
327
349
|
end
|
350
|
+
|
351
|
+
# Minitest
|
352
|
+
def test_no_notification_if_event_is_not_found
|
353
|
+
assert_no_deliveries do
|
354
|
+
some_action
|
355
|
+
end
|
356
|
+
|
357
|
+
# Alternatively, you can use the positive assertion
|
358
|
+
assert_deliveries(0) do
|
359
|
+
some_action
|
360
|
+
end
|
361
|
+
end
|
328
362
|
```
|
329
363
|
|
330
|
-
|
364
|
+
With RSpec, you can also use the `#have_not_delivered_to` matcher:
|
331
365
|
|
332
366
|
```ruby
|
333
367
|
specify "when event is not found" do
|
@@ -360,7 +394,7 @@ describe PostsDelivery do
|
|
360
394
|
end
|
361
395
|
```
|
362
396
|
|
363
|
-
You can also use the `#deliver_via`
|
397
|
+
You can also use the `#deliver_via` RSpec matcher as follows:
|
364
398
|
|
365
399
|
```ruby
|
366
400
|
describe PostsDelivery, type: :delivery do
|
@@ -387,8 +421,6 @@ describe PostsDelivery, type: :delivery do
|
|
387
421
|
end
|
388
422
|
```
|
389
423
|
|
390
|
-
**NOTE:** test mode activated automatically if `RAILS_ENV` or `RACK_ENV` env variable is equal to "test". Otherwise, add `require "active_delivery/testing/rspec"` to your `spec_helper.rb` / `rails_helper.rb` manually. This is also required if you're using Spring in the test environment (e.g. with help of [spring-commands-rspec](https://github.com/jonleighton/spring-commands-rspec)).
|
391
|
-
|
392
424
|
## Custom "lines"
|
393
425
|
|
394
426
|
The _Line_ class describes the way you want to _transfer_ your deliveries.
|
@@ -410,8 +442,8 @@ class EventPigeon
|
|
410
442
|
alias_method :with, :new
|
411
443
|
|
412
444
|
# delegate delivery action to the instance
|
413
|
-
def message_arrived(*
|
414
|
-
new.message_arrived(*
|
445
|
+
def message_arrived(*)
|
446
|
+
new.message_arrived(*)
|
415
447
|
end
|
416
448
|
end
|
417
449
|
|
@@ -447,17 +479,17 @@ class PigeonLine < ActiveDelivery::Lines::Base
|
|
447
479
|
# Called when we want to send message synchronously
|
448
480
|
# `sender` here either `sender_class` or `sender_class.with(params)`
|
449
481
|
# if params passed.
|
450
|
-
def notify_now(sender, delivery_action,
|
482
|
+
def notify_now(sender, delivery_action, *, **)
|
451
483
|
# For example, our EventPigeon class returns some `Pigeon` object
|
452
|
-
pigeon = sender.public_send(delivery_action,
|
484
|
+
pigeon = sender.public_send(delivery_action, *, **)
|
453
485
|
# PigeonLaunchService do all the sending job
|
454
486
|
PigeonService.launch pigeon
|
455
487
|
end
|
456
488
|
|
457
489
|
# Called when we want to send a message asynchronously.
|
458
490
|
# For example, you can use a background job here.
|
459
|
-
def notify_later(sender, delivery_action,
|
460
|
-
pigeon = sender.public_send(delivery_action,
|
491
|
+
def notify_later(sender, delivery_action, *, **)
|
492
|
+
pigeon = sender.public_send(delivery_action, *, **)
|
461
493
|
# PigeonLaunchService do all the sending job
|
462
494
|
PigeonLaunchJob.perform_later pigeon
|
463
495
|
end
|
@@ -475,8 +507,8 @@ class EventPigeon
|
|
475
507
|
alias_method :with, :new
|
476
508
|
|
477
509
|
# delegate delivery action to the instance
|
478
|
-
def message_arrived(*
|
479
|
-
new.message_arrived(*
|
510
|
+
def message_arrived(*)
|
511
|
+
new.message_arrived(*)
|
480
512
|
end
|
481
513
|
end
|
482
514
|
|
@@ -491,18 +523,18 @@ class EventPigeon
|
|
491
523
|
end
|
492
524
|
|
493
525
|
class PigeonLine < ActiveDelivery::Lines::Base
|
494
|
-
def notify_later(sender, delivery_action,
|
526
|
+
def notify_later(sender, delivery_action, *, **kwargs)
|
495
527
|
# `to_s` is important for serialization. Unless you might have error
|
496
|
-
PigeonLaunchJob.perform_later
|
528
|
+
PigeonLaunchJob.perform_later(sender.class.to_s, delivery_action, *, **kwargs.merge(params: line.params))
|
497
529
|
end
|
498
530
|
end
|
499
531
|
|
500
532
|
class PigeonLaunchJob < ActiveJob::Base
|
501
|
-
def perform(sender, delivery_action,
|
533
|
+
def perform(sender, delivery_action, *, params: nil, **)
|
502
534
|
klass = sender.safe_constantize
|
503
535
|
handler = params ? klass.with(**params) : klass.new
|
504
536
|
|
505
|
-
handler.public_send(delivery_action,
|
537
|
+
handler.public_send(delivery_action, *, **)
|
506
538
|
end
|
507
539
|
end
|
508
540
|
```
|
@@ -591,12 +623,12 @@ class ActionCableDeliveryLine < ActiveDelivery::Line::Base
|
|
591
623
|
# We want to broadcast all notifications
|
592
624
|
def notify?(...) = true
|
593
625
|
|
594
|
-
def notify_now(context, delivery_action,
|
626
|
+
def notify_now(context, delivery_action, *, **)
|
595
627
|
# Skip if no user provided
|
596
628
|
return unless context.user
|
597
629
|
|
598
630
|
payload = {event: [context.scope, delivery_action].join(".")}
|
599
|
-
payload.merge!(serialized_args(
|
631
|
+
payload.merge!(serialized_args(*, **))
|
600
632
|
|
601
633
|
DeliveryChannel.broadcast_to context.user, payload
|
602
634
|
end
|
@@ -22,8 +22,8 @@ module AbstractNotifier
|
|
22
22
|
job.set(queue: queue).perform_later(...)
|
23
23
|
end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :enqueue)
|
24
24
|
|
25
|
-
def enqueue_delivery(delivery, **
|
26
|
-
job.set(queue: queue, **
|
25
|
+
def enqueue_delivery(delivery, **__kwrest__)
|
26
|
+
job.set(queue: queue, **__kwrest__).perform_later(
|
27
27
|
delivery.notifier_class.name,
|
28
28
|
delivery.action_name,
|
29
29
|
**delivery.delivery_params
|
@@ -23,9 +23,9 @@ module AbstractNotifier
|
|
23
23
|
|
24
24
|
alias_method :notification, :processed
|
25
25
|
|
26
|
-
def notify_later(**
|
26
|
+
def notify_later(**__kwrest__)
|
27
27
|
if notifier_class.async_adapter.respond_to?(:enqueue_delivery)
|
28
|
-
notifier_class.async_adapter.enqueue_delivery(self, **
|
28
|
+
notifier_class.async_adapter.enqueue_delivery(self, **__kwrest__)
|
29
29
|
else
|
30
30
|
notifier_class.async_adapter.enqueue(notifier_class.name, action_name, params: params, args: args, kwargs: kwargs)
|
31
31
|
end
|
@@ -73,8 +73,8 @@ module AbstractNotifier
|
|
73
73
|
end
|
74
74
|
# rubocop:enable Style/MethodMissingSuper
|
75
75
|
|
76
|
-
def respond_to_missing?(*
|
77
|
-
notifier_class.respond_to_missing?(*
|
76
|
+
def respond_to_missing?(*__rest__)
|
77
|
+
notifier_class.respond_to_missing?(*__rest__)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -77,8 +77,8 @@ module ActiveDelivery
|
|
77
77
|
|
78
78
|
# The same as .notify but delivers synchronously
|
79
79
|
# (i.e. #deliver_now for mailers)
|
80
|
-
def notify!(mid, *
|
81
|
-
notify(mid, *
|
80
|
+
def notify!(mid, *__rest__, **hargs)
|
81
|
+
notify(mid, *__rest__, **hargs, sync: true)
|
82
82
|
end
|
83
83
|
|
84
84
|
alias_method :notify_now, :notify!
|
@@ -93,7 +93,7 @@ module ActiveDelivery
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
def register_line(line_id, line_class = nil, notifier: nil, **
|
96
|
+
def register_line(line_id, line_class = nil, notifier: nil, **__kwrest__)
|
97
97
|
raise ArgumentError, "A line class or notifier configuration must be provided" if line_class.nil? && notifier.nil?
|
98
98
|
|
99
99
|
# Configure Notifier
|
@@ -101,7 +101,7 @@ module ActiveDelivery
|
|
101
101
|
line_class = ActiveDelivery::Lines::Notifier
|
102
102
|
end
|
103
103
|
|
104
|
-
delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **
|
104
|
+
delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **__kwrest__)
|
105
105
|
|
106
106
|
instance_eval <<~CODE, __FILE__, __LINE__ + 1
|
107
107
|
def #{line_id}(val)
|
@@ -152,13 +152,13 @@ module ActiveDelivery
|
|
152
152
|
super
|
153
153
|
end
|
154
154
|
|
155
|
-
def method_missing(mid, *
|
155
|
+
def method_missing(mid, *__rest__, **__kwrest__)
|
156
156
|
return super unless respond_to_missing?(mid)
|
157
157
|
|
158
158
|
# Lazily define a class method to avoid lookups
|
159
159
|
delivers(mid)
|
160
160
|
|
161
|
-
public_send(mid, *
|
161
|
+
public_send(mid, *__rest__, **__kwrest__)
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
@@ -197,7 +197,7 @@ module ActiveDelivery
|
|
197
197
|
super
|
198
198
|
end
|
199
199
|
|
200
|
-
def method_missing(mid, *
|
200
|
+
def method_missing(mid, *__rest__, **__kwrest__)
|
201
201
|
return super unless respond_to_missing?(mid)
|
202
202
|
|
203
203
|
# Lazily define a method to avoid future lookups
|
@@ -211,7 +211,7 @@ module ActiveDelivery
|
|
211
211
|
end
|
212
212
|
CODE
|
213
213
|
|
214
|
-
public_send(mid, *
|
214
|
+
public_send(mid, *__rest__, **__kwrest__)
|
215
215
|
end
|
216
216
|
|
217
217
|
protected
|
@@ -41,16 +41,16 @@ module ActiveDelivery
|
|
41
41
|
notify_later(handler, mid, *__rest__, &__block__)
|
42
42
|
end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :notify_later_with_options)
|
43
43
|
|
44
|
-
def notify(mid, *
|
44
|
+
def notify(mid, *__rest__, params:, sync:, enqueue_options:, **__kwrest__)
|
45
45
|
clazz = params.empty? ? handler_class : handler_class.with(**params)
|
46
46
|
if sync
|
47
|
-
return notify_now(clazz, mid, *
|
47
|
+
return notify_now(clazz, mid, *__rest__, **__kwrest__)
|
48
48
|
end
|
49
49
|
|
50
50
|
if enqueue_options.empty?
|
51
|
-
notify_later(clazz, mid, *
|
51
|
+
notify_later(clazz, mid, *__rest__, **__kwrest__)
|
52
52
|
else
|
53
|
-
notify_later_with_options(clazz, enqueue_options, mid, *
|
53
|
+
notify_later_with_options(clazz, enqueue_options, mid, *__rest__, **__kwrest__)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveDelivery
|
4
|
+
module TestHelper
|
5
|
+
def assert_deliveries(count)
|
6
|
+
TestDelivery.enable { yield }
|
7
|
+
|
8
|
+
assert_equal TestDelivery.store.count, count, "Expected #{count} deliveries, got #{TestDelivery.store.count}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_no_deliveries(&__block__) ; assert_deliveries(0, &__block__); end
|
12
|
+
|
13
|
+
def assert_delivery_enqueued(delivery_class, event, count: 1, params: nil, with: nil)
|
14
|
+
TestDelivery.enable { yield }
|
15
|
+
|
16
|
+
deliveries = TestDelivery.store
|
17
|
+
|
18
|
+
if with
|
19
|
+
args = with
|
20
|
+
kwargs = args.pop if args.last.is_a?(Hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
matching_deliveries, _unmatching_deliveries =
|
24
|
+
deliveries.partition do |(delivery, options)|
|
25
|
+
next false if delivery_class != delivery.owner.class
|
26
|
+
|
27
|
+
next false if event != delivery.notification
|
28
|
+
|
29
|
+
next false if params && !hash_include?(delivery.owner.params, params)
|
30
|
+
|
31
|
+
next true unless with
|
32
|
+
|
33
|
+
actual_args = delivery.params
|
34
|
+
actual_kwargs = delivery.options
|
35
|
+
|
36
|
+
next false unless args.each.with_index.all? do |arg, i|
|
37
|
+
arg === actual_args[i]
|
38
|
+
end
|
39
|
+
|
40
|
+
next false unless kwargs.all? do |k, v|
|
41
|
+
v === actual_kwargs[k]
|
42
|
+
end
|
43
|
+
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_equal count, matching_deliveries.count, "Expected #{count} deliveries, got #{deliveries.count}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def hash_include?(haystack, needle)
|
53
|
+
needle.all? do |k, v|
|
54
|
+
haystack.key?(k) && haystack[k] == v
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -22,8 +22,8 @@ module AbstractNotifier
|
|
22
22
|
job.set(queue: queue).perform_later(...)
|
23
23
|
end
|
24
24
|
|
25
|
-
def enqueue_delivery(delivery, **
|
26
|
-
job.set(queue: queue, **
|
25
|
+
def enqueue_delivery(delivery, **__kwrest__)
|
26
|
+
job.set(queue: queue, **__kwrest__).perform_later(
|
27
27
|
delivery.notifier_class.name,
|
28
28
|
delivery.action_name,
|
29
29
|
**delivery.delivery_params
|
@@ -23,9 +23,9 @@ module AbstractNotifier
|
|
23
23
|
|
24
24
|
alias_method :notification, :processed
|
25
25
|
|
26
|
-
def notify_later(**
|
26
|
+
def notify_later(**__kwrest__)
|
27
27
|
if notifier_class.async_adapter.respond_to?(:enqueue_delivery)
|
28
|
-
notifier_class.async_adapter.enqueue_delivery(self, **
|
28
|
+
notifier_class.async_adapter.enqueue_delivery(self, **__kwrest__)
|
29
29
|
else
|
30
30
|
notifier_class.async_adapter.enqueue(notifier_class.name, action_name, params: params, args: args, kwargs: kwargs)
|
31
31
|
end
|
@@ -73,8 +73,8 @@ module AbstractNotifier
|
|
73
73
|
end
|
74
74
|
# rubocop:enable Style/MethodMissingSuper
|
75
75
|
|
76
|
-
def respond_to_missing?(*
|
77
|
-
notifier_class.respond_to_missing?(*
|
76
|
+
def respond_to_missing?(*__rest__)
|
77
|
+
notifier_class.respond_to_missing?(*__rest__)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -77,8 +77,8 @@ module ActiveDelivery
|
|
77
77
|
|
78
78
|
# The same as .notify but delivers synchronously
|
79
79
|
# (i.e. #deliver_now for mailers)
|
80
|
-
def notify!(mid, *
|
81
|
-
notify(mid, *
|
80
|
+
def notify!(mid, *__rest__, **hargs)
|
81
|
+
notify(mid, *__rest__, **hargs, sync: true)
|
82
82
|
end
|
83
83
|
|
84
84
|
alias_method :notify_now, :notify!
|
@@ -93,7 +93,7 @@ module ActiveDelivery
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
def register_line(line_id, line_class = nil, notifier: nil, **
|
96
|
+
def register_line(line_id, line_class = nil, notifier: nil, **__kwrest__)
|
97
97
|
raise ArgumentError, "A line class or notifier configuration must be provided" if line_class.nil? && notifier.nil?
|
98
98
|
|
99
99
|
# Configure Notifier
|
@@ -101,7 +101,7 @@ module ActiveDelivery
|
|
101
101
|
line_class = ActiveDelivery::Lines::Notifier
|
102
102
|
end
|
103
103
|
|
104
|
-
delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **
|
104
|
+
delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **__kwrest__)
|
105
105
|
|
106
106
|
instance_eval <<~CODE, __FILE__, __LINE__ + 1
|
107
107
|
def #{line_id}(val)
|
@@ -152,13 +152,13 @@ module ActiveDelivery
|
|
152
152
|
super
|
153
153
|
end
|
154
154
|
|
155
|
-
def method_missing(mid, *
|
155
|
+
def method_missing(mid, *__rest__, **__kwrest__)
|
156
156
|
return super unless respond_to_missing?(mid)
|
157
157
|
|
158
158
|
# Lazily define a class method to avoid lookups
|
159
159
|
delivers(mid)
|
160
160
|
|
161
|
-
public_send(mid, *
|
161
|
+
public_send(mid, *__rest__, **__kwrest__)
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
@@ -197,7 +197,7 @@ module ActiveDelivery
|
|
197
197
|
super
|
198
198
|
end
|
199
199
|
|
200
|
-
def method_missing(mid, *
|
200
|
+
def method_missing(mid, *__rest__, **__kwrest__)
|
201
201
|
return super unless respond_to_missing?(mid)
|
202
202
|
|
203
203
|
# Lazily define a method to avoid future lookups
|
@@ -211,7 +211,7 @@ module ActiveDelivery
|
|
211
211
|
end
|
212
212
|
CODE
|
213
213
|
|
214
|
-
public_send(mid, *
|
214
|
+
public_send(mid, *__rest__, **__kwrest__)
|
215
215
|
end
|
216
216
|
|
217
217
|
protected
|
@@ -41,16 +41,16 @@ module ActiveDelivery
|
|
41
41
|
notify_later(handler, mid, ...)
|
42
42
|
end
|
43
43
|
|
44
|
-
def notify(mid, *
|
44
|
+
def notify(mid, *__rest__, params:, sync:, enqueue_options:, **__kwrest__)
|
45
45
|
clazz = params.empty? ? handler_class : handler_class.with(**params)
|
46
46
|
if sync
|
47
|
-
return notify_now(clazz, mid, *
|
47
|
+
return notify_now(clazz, mid, *__rest__, **__kwrest__)
|
48
48
|
end
|
49
49
|
|
50
50
|
if enqueue_options.empty?
|
51
|
-
notify_later(clazz, mid, *
|
51
|
+
notify_later(clazz, mid, *__rest__, **__kwrest__)
|
52
52
|
else
|
53
|
-
notify_later_with_options(clazz, enqueue_options, mid, *
|
53
|
+
notify_later_with_options(clazz, enqueue_options, mid, *__rest__, **__kwrest__)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveDelivery
|
4
|
+
module TestHelper
|
5
|
+
def assert_deliveries(count)
|
6
|
+
TestDelivery.enable { yield }
|
7
|
+
|
8
|
+
assert_equal TestDelivery.store.count, count, "Expected #{count} deliveries, got #{TestDelivery.store.count}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_no_deliveries(&__block__) = assert_deliveries(0, &__block__)
|
12
|
+
|
13
|
+
def assert_delivery_enqueued(delivery_class, event, count: 1, params: nil, with: nil)
|
14
|
+
TestDelivery.enable { yield }
|
15
|
+
|
16
|
+
deliveries = TestDelivery.store
|
17
|
+
|
18
|
+
if with
|
19
|
+
args = with
|
20
|
+
kwargs = args.pop if args.last.is_a?(Hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
matching_deliveries, _unmatching_deliveries =
|
24
|
+
deliveries.partition do |(delivery, options)|
|
25
|
+
next false if delivery_class != delivery.owner.class
|
26
|
+
|
27
|
+
next false if event != delivery.notification
|
28
|
+
|
29
|
+
next false if params && !hash_include?(delivery.owner.params, params)
|
30
|
+
|
31
|
+
next true unless with
|
32
|
+
|
33
|
+
actual_args = delivery.params
|
34
|
+
actual_kwargs = delivery.options
|
35
|
+
|
36
|
+
next false unless args.each.with_index.all? do |arg, i|
|
37
|
+
arg === actual_args[i]
|
38
|
+
end
|
39
|
+
|
40
|
+
next false unless kwargs.all? do |k, v|
|
41
|
+
v === actual_kwargs[k]
|
42
|
+
end
|
43
|
+
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_equal count, matching_deliveries.count, "Expected #{count} deliveries, got #{deliveries.count}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def hash_include?(haystack, needle)
|
53
|
+
needle.all? do |k, v|
|
54
|
+
haystack.key?(k) && haystack[k] == v
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AbstractNotifier
|
4
|
+
module AsyncAdapters
|
5
|
+
class ActiveJob
|
6
|
+
class DeliveryJob < ::ActiveJob::Base
|
7
|
+
def perform(notifier_class, ...)
|
8
|
+
AbstractNotifier::NotificationDelivery.new(notifier_class.constantize, ...).notify_now
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
DEFAULT_QUEUE = "notifiers"
|
13
|
+
|
14
|
+
attr_reader :job, :queue
|
15
|
+
|
16
|
+
def initialize(queue: DEFAULT_QUEUE, job: DeliveryJob)
|
17
|
+
@job = job
|
18
|
+
@queue = queue
|
19
|
+
end
|
20
|
+
|
21
|
+
def enqueue(...)
|
22
|
+
job.set(queue:).perform_later(...)
|
23
|
+
end
|
24
|
+
|
25
|
+
def enqueue_delivery(delivery, **__kwrest__)
|
26
|
+
job.set(queue:, **__kwrest__).perform_later(
|
27
|
+
delivery.notifier_class.name,
|
28
|
+
delivery.action_name,
|
29
|
+
**delivery.delivery_params
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
AbstractNotifier.async_adapter ||= :active_job
|