noticed 2.1.3 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +39 -23
- data/app/jobs/noticed/event_job.rb +3 -3
- data/app/models/concerns/noticed/deliverable.rb +5 -0
- data/app/models/noticed/deliverable/deliver_by.rb +25 -13
- data/app/models/noticed/ephemeral.rb +4 -4
- data/db/migrate/20231215190233_create_noticed_tables.rb +16 -5
- data/lib/generators/noticed/templates/notifier.rb.tt +1 -1
- data/lib/noticed/api_client.rb +1 -1
- data/lib/noticed/delivery_methods/ios.rb +1 -1
- data/lib/noticed/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7df6a0c9d61e67b03bdb4fa83ac6cf3ef46b1b79b23ac98f1b0acdf1b02b336a
|
4
|
+
data.tar.gz: f457d0616b83add859fb1660cc53f2bf321f3631c25e6d9403bf52d84246be43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc114600b94adafc1fb4c01034cfd31e70acda183e5734a31f5ea1d5408272b93b5545dad3861394e0af2944aa2f95765a14689130d8f49479925e3a17f35c2b
|
7
|
+
data.tar.gz: a5e8cc9353874c01f45c286ced403446196be57d241ca1c534b365df1869a560fe08e6c65655e8bb246e672728dd2edb8a394de68111c94b0446513e93b52f9c
|
data/README.md
CHANGED
@@ -71,7 +71,7 @@ Noticed operates with a few constructs: Notifiers, delivery methods, and Notific
|
|
71
71
|
|
72
72
|
To start, generate a Notifier:
|
73
73
|
|
74
|
-
```
|
74
|
+
```bash
|
75
75
|
rails generate noticed:notifier NewCommentNotifier
|
76
76
|
```
|
77
77
|
|
@@ -202,12 +202,12 @@ class CommentNotifier < Noticed::Event
|
|
202
202
|
end
|
203
203
|
end
|
204
204
|
|
205
|
-
class
|
205
|
+
class Recipient < ApplicationRecord # or whatever your recipient model is
|
206
206
|
has_many :ios_device_tokens
|
207
207
|
|
208
|
-
|
209
|
-
|
210
|
-
|
208
|
+
def send_ios_notification?
|
209
|
+
# some logic
|
210
|
+
end
|
211
211
|
end
|
212
212
|
```
|
213
213
|
</details>
|
@@ -297,16 +297,16 @@ Will look for the following translation path:
|
|
297
297
|
|
298
298
|
en:
|
299
299
|
notifiers:
|
300
|
-
|
301
|
-
|
302
|
-
|
300
|
+
new_comment_notifier:
|
301
|
+
notification:
|
302
|
+
message: "Someone posted a new comment!"
|
303
303
|
```
|
304
304
|
|
305
305
|
Or, if you have your Notifier within another module, such as `Admin::NewCommentNotifier`, the resulting lookup path will be `en.notifiers.admin.new_comment_notifier.notification.message` (modules become nesting steps).
|
306
306
|
|
307
307
|
#### Tip: Capture User Preferences
|
308
308
|
|
309
|
-
You can use the `if:` and `unless
|
309
|
+
You can use the `if:` and `unless:` options on your delivery methods to check the user's preferences and skip processing if they have disabled that type of notification.
|
310
310
|
|
311
311
|
For example:
|
312
312
|
|
@@ -319,6 +319,19 @@ class CommentNotifier < Noticed::Event
|
|
319
319
|
end
|
320
320
|
end
|
321
321
|
```
|
322
|
+
|
323
|
+
If you would like to skip the delivery job altogether, for example if you know that a user doesn't support the platform and you would like to save resources by not enqueuing the job, you can use `before_enqueue`.
|
324
|
+
|
325
|
+
For example:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
class IosNotifier < Noticed::Event
|
329
|
+
deliver_by :ios do |config|
|
330
|
+
# ...
|
331
|
+
config.before_enqueue = ->{ throw(:abort) unless recipient.registered_ios? }
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
322
335
|
#### Tip: Extracting Delivery Method Configurations
|
323
336
|
|
324
337
|
If you want to reuse delivery method configurations across multiple Notifiers, you can extract them into a module and include them in your Notifiers.
|
@@ -348,7 +361,7 @@ module IosNotifier
|
|
348
361
|
config.key_id = Rails.application.credentials.dig(:ios, :key_id)
|
349
362
|
config.team_id = Rails.application.credentials.dig(:ios, :team_id)
|
350
363
|
config.apns_key = Rails.application.credentials.dig(:ios, :apns_key)
|
351
|
-
config.if = ->
|
364
|
+
config.if = -> { recipient.ios_notifications? }
|
352
365
|
end
|
353
366
|
end
|
354
367
|
end
|
@@ -361,8 +374,8 @@ Each of these options are available for every delivery method (individual or bul
|
|
361
374
|
* `config.if` — Intended for a lambda or method; runs after the `wait` if configured; cancels the delivery method if returns falsey
|
362
375
|
* `config.unless` — Intended for a lambda or method; runs after the `wait` if configured; cancels the delivery method if returns truthy
|
363
376
|
* `config.wait` — (Should yield an `ActiveSupport::Duration`) Delays the job that runs this delivery method for the given duration of time
|
364
|
-
* `config.wait_until` —
|
365
|
-
* `config.queue`
|
377
|
+
* `config.wait_until` — (Should yield a specific time object) Delays the job that runs this delivery method until the specific time specified
|
378
|
+
* `config.queue` — Sets the ActiveJob queue name to be used for the job that runs this delivery method
|
366
379
|
|
367
380
|
### 📨 Sending Notifications
|
368
381
|
|
@@ -387,7 +400,7 @@ This invocation will create a single `Noticed::Event` record and a `Noticed::Not
|
|
387
400
|
|
388
401
|
### Custom Noticed Model Methods
|
389
402
|
|
390
|
-
In order to extend the Noticed models you'll need to use a concern
|
403
|
+
In order to extend the Noticed models you'll need to use a concern and a to_prepare block:
|
391
404
|
|
392
405
|
```ruby
|
393
406
|
# config/initializers/noticed.rb
|
@@ -395,7 +408,7 @@ module NotificationExtensions
|
|
395
408
|
extend ActiveSupport::Concern
|
396
409
|
|
397
410
|
included do
|
398
|
-
belongs_to :
|
411
|
+
belongs_to :organization
|
399
412
|
|
400
413
|
scope :filter_by_type, ->(type) { where(type:) }
|
401
414
|
scope :exclude_type, ->(type) { where.not(type:) }
|
@@ -489,7 +502,7 @@ Sending a notification is entirely an internal-to-your-app function. Delivery me
|
|
489
502
|
A common pattern is to deliver a notification via a real (or real-ish)-time service, then, after some time has passed, email the user if they have not yet read the notification. You can implement this functionality by combining multiple delivery methods, the `wait` option, and the conditional `if` / `unless` option.
|
490
503
|
|
491
504
|
```ruby
|
492
|
-
class NewCommentNotifier< Noticed::Event
|
505
|
+
class NewCommentNotifier < Noticed::Event
|
493
506
|
deliver_by :action_cable
|
494
507
|
deliver_by :email do |config|
|
495
508
|
config.mailer = "CommentMailer"
|
@@ -544,6 +557,7 @@ See the [Custom Noticed Model Methods](#custom-noticed-model-methods) section fo
|
|
544
557
|
|
545
558
|
```ruby
|
546
559
|
# app/notifiers/delivery_methods/turbo_stream.rb
|
560
|
+
|
547
561
|
class DeliveryMethods::TurboStream < ApplicationDeliveryMethod
|
548
562
|
def deliver
|
549
563
|
return unless recipient.is_a?(User)
|
@@ -557,6 +571,7 @@ end
|
|
557
571
|
|
558
572
|
```ruby
|
559
573
|
# app/models/concerns/noticed/notification_extensions.rb
|
574
|
+
|
560
575
|
module Noticed::NotificationExtensions
|
561
576
|
extend ActiveSupport::Concern
|
562
577
|
|
@@ -592,12 +607,12 @@ end
|
|
592
607
|
|
593
608
|
Delivery methods have access to the following methods and attributes:
|
594
609
|
|
595
|
-
* `event` —
|
596
|
-
* `record` —
|
597
|
-
* `notification` —
|
598
|
-
* `recipient` —
|
599
|
-
* `config` —
|
600
|
-
* `params` —
|
610
|
+
* `event` — The `Noticed::Event` record that spawned the notification object currently being delivered
|
611
|
+
* `record` — The object originally passed into the Notifier as the `record:` param (see the ✨ note above)
|
612
|
+
* `notification` — The `Noticed::Notification` instance being delivered. All notification helper methods are available on this object
|
613
|
+
* `recipient` — The individual recipient object being delivered to for this notification (remember that each recipient gets their own instance of the Delivery Method `#deliver`)
|
614
|
+
* `config` — The hash of configuration options declared by the Notifier that generated this notification and delivery
|
615
|
+
* `params` — The parameters given to the Notifier in the invocation (via `.with()`)
|
601
616
|
|
602
617
|
#### Validating config options passed to Custom Delivery methods
|
603
618
|
|
@@ -628,7 +643,7 @@ class DeliveryMethods::WhatsApp < Noticed::DeliveryMethod
|
|
628
643
|
|
629
644
|
def deliver
|
630
645
|
# ...
|
631
|
-
|
646
|
+
config.day #=> #<Proc:0x000f7c8 (lambda)>
|
632
647
|
evaluate_option(config.day) #=> "Tuesday"
|
633
648
|
end
|
634
649
|
end
|
@@ -766,7 +781,7 @@ class CreateNoticedTables < ActiveRecord::Migration[7.1]
|
|
766
781
|
t.jsonb :params
|
767
782
|
|
768
783
|
# Custom Fields
|
769
|
-
t.string :
|
784
|
+
t.string :organization_id, type: :uuid, as: "((params ->> 'organization_id')::uuid)", stored: true
|
770
785
|
t.virtual :action_type, type: :string, as: "((params ->> 'action_type'))", stored: true
|
771
786
|
t.virtual :url, type: :string, as: "((params ->> 'url'))", stored: true
|
772
787
|
|
@@ -803,4 +818,5 @@ DATABASE_URL=postgres://127.0.0.1/noticed_test rails test
|
|
803
818
|
```
|
804
819
|
|
805
820
|
## 📝 License
|
821
|
+
|
806
822
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -4,14 +4,14 @@ module Noticed
|
|
4
4
|
|
5
5
|
def perform(event)
|
6
6
|
# Enqueue bulk deliveries
|
7
|
-
event.bulk_delivery_methods.
|
7
|
+
event.bulk_delivery_methods.each_value do |deliver_by|
|
8
8
|
deliver_by.perform_later(event)
|
9
9
|
end
|
10
10
|
|
11
11
|
# Enqueue individual deliveries
|
12
12
|
event.notifications.each do |notification|
|
13
|
-
event.delivery_methods.
|
14
|
-
deliver_by.perform_later(notification)
|
13
|
+
event.delivery_methods.each_value do |deliver_by|
|
14
|
+
deliver_by.perform_later(notification) if deliver_by.perform?(notification)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -138,5 +138,10 @@ module Noticed
|
|
138
138
|
bulk_delivery_methods.values.each(&:validate!)
|
139
139
|
delivery_methods.values.each(&:validate!)
|
140
140
|
end
|
141
|
+
|
142
|
+
# If a GlobalID record in params is no longer found, the params will default with a noticed_error key
|
143
|
+
def deserialize_error?
|
144
|
+
!!params[:noticed_error]
|
145
|
+
end
|
141
146
|
end
|
142
147
|
end
|
@@ -19,27 +19,18 @@ module Noticed
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def perform_later(event_or_notification, options = {})
|
22
|
-
options
|
23
|
-
options[:wait_until] ||= evaluate_option(:wait_until, event_or_notification) if config.has_key?(:wait_until)
|
24
|
-
options[:queue] ||= evaluate_option(:queue, event_or_notification) if config.has_key?(:queue)
|
25
|
-
options[:priority] ||= evaluate_option(:priority, event_or_notification) if config.has_key?(:priority)
|
26
|
-
|
27
|
-
constant.set(options).perform_later(name, event_or_notification)
|
22
|
+
constant.set(computed_options(options, event_or_notification)).perform_later(name, event_or_notification)
|
28
23
|
end
|
29
24
|
|
30
25
|
def ephemeral_perform_later(notifier, recipient, params, options = {})
|
31
|
-
options
|
32
|
-
|
33
|
-
options[:queue] ||= evaluate_option(:queue, recipient) if config.has_key?(:queue)
|
34
|
-
options[:priority] ||= evaluate_option(:priority, recipient) if config.has_key?(:priority)
|
35
|
-
|
36
|
-
constant.set(options).perform_later(name, "#{notifier}::Notification", recipient: recipient, params: params)
|
26
|
+
constant.set(computed_options(options, recipient))
|
27
|
+
.perform_later(name, "#{notifier}::Notification", recipient: recipient, params: params)
|
37
28
|
end
|
38
29
|
|
39
30
|
def evaluate_option(name, context)
|
40
31
|
option = config[name]
|
41
32
|
|
42
|
-
if option
|
33
|
+
if option.respond_to?(:call)
|
43
34
|
context.instance_exec(&option)
|
44
35
|
elsif option.is_a?(Symbol) && context.respond_to?(option)
|
45
36
|
context.send(option)
|
@@ -47,6 +38,27 @@ module Noticed
|
|
47
38
|
option
|
48
39
|
end
|
49
40
|
end
|
41
|
+
|
42
|
+
def perform?(notification)
|
43
|
+
return true unless config.key?(:before_enqueue)
|
44
|
+
|
45
|
+
perform = false
|
46
|
+
catch(:abort) {
|
47
|
+
evaluate_option(:before_enqueue, notification)
|
48
|
+
perform = true
|
49
|
+
}
|
50
|
+
perform
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def computed_options(options, recipient)
|
56
|
+
options[:wait] ||= evaluate_option(:wait, recipient) if config.has_key?(:wait)
|
57
|
+
options[:wait_until] ||= evaluate_option(:wait_until, recipient) if config.has_key?(:wait_until)
|
58
|
+
options[:queue] ||= evaluate_option(:queue, recipient) if config.has_key?(:queue)
|
59
|
+
options[:priority] ||= evaluate_option(:priority, recipient) if config.has_key?(:priority)
|
60
|
+
options
|
61
|
+
end
|
50
62
|
end
|
51
63
|
end
|
52
64
|
end
|
@@ -29,6 +29,10 @@ module Noticed
|
|
29
29
|
notifier.const_set :Notification, Class.new(Noticed::Ephemeral::Notification)
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.notification_methods(&block)
|
33
|
+
const_get(:Notification).class_eval(&block)
|
34
|
+
end
|
35
|
+
|
32
36
|
def deliver(recipients)
|
33
37
|
recipients = Array.wrap(recipients)
|
34
38
|
bulk_delivery_methods.each do |_, deliver_by|
|
@@ -45,9 +49,5 @@ module Noticed
|
|
45
49
|
def record
|
46
50
|
params[:record]
|
47
51
|
end
|
48
|
-
|
49
|
-
def notification_methods(&block)
|
50
|
-
const_get(:Notification).class_eval(&block)
|
51
|
-
end
|
52
52
|
end
|
53
53
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
class CreateNoticedTables < ActiveRecord::Migration[6.1]
|
2
2
|
def change
|
3
|
-
|
3
|
+
primary_key_type, foreign_key_type = primary_and_foreign_key_types
|
4
|
+
create_table :noticed_events, id: primary_key_type do |t|
|
4
5
|
t.string :type
|
5
|
-
t.belongs_to :record, polymorphic: true
|
6
|
+
t.belongs_to :record, polymorphic: true, type: foreign_key_type
|
6
7
|
if t.respond_to?(:jsonb)
|
7
8
|
t.jsonb :params
|
8
9
|
else
|
@@ -12,14 +13,24 @@ class CreateNoticedTables < ActiveRecord::Migration[6.1]
|
|
12
13
|
t.timestamps
|
13
14
|
end
|
14
15
|
|
15
|
-
create_table :noticed_notifications do |t|
|
16
|
+
create_table :noticed_notifications, id: primary_key_type do |t|
|
16
17
|
t.string :type
|
17
|
-
t.belongs_to :event, null: false
|
18
|
-
t.belongs_to :recipient, polymorphic: true, null: false
|
18
|
+
t.belongs_to :event, null: false, type: foreign_key_type
|
19
|
+
t.belongs_to :recipient, polymorphic: true, null: false, type: foreign_key_type
|
19
20
|
t.datetime :read_at
|
20
21
|
t.datetime :seen_at
|
21
22
|
|
22
23
|
t.timestamps
|
23
24
|
end
|
24
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def primary_and_foreign_key_types
|
30
|
+
config = Rails.configuration.generators
|
31
|
+
setting = config.options[config.orm][:primary_key_type]
|
32
|
+
primary_key_type = setting || :primary_key
|
33
|
+
foreign_key_type = setting || :bigint
|
34
|
+
[primary_key_type, foreign_key_type]
|
35
|
+
end
|
25
36
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# To deliver this notification:
|
2
2
|
#
|
3
|
-
# <%= class_name
|
3
|
+
# <%= class_name %>Notifier.with(record: @post, message: "New post").deliver(User.all)
|
4
4
|
|
5
5
|
class <%= class_name %>Notifier < ApplicationNotifier
|
6
6
|
# Add your delivery methods
|
data/lib/noticed/api_client.rb
CHANGED
@@ -35,7 +35,7 @@ module Noticed
|
|
35
35
|
method = config[:format]
|
36
36
|
# Call method on Notifier if defined
|
37
37
|
if method&.is_a?(Symbol) && event.respond_to?(method)
|
38
|
-
event.send(method, apn)
|
38
|
+
event.send(method, notification, apn)
|
39
39
|
# If Proc, evaluate it on the Notification
|
40
40
|
elsif method&.respond_to?(:call)
|
41
41
|
notification.instance_exec(apn, &method)
|
data/lib/noticed/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: noticed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Oliver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|