noticed 1.0.0 → 1.2.20
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/README.md +364 -60
- data/Rakefile +4 -0
- data/lib/generators/noticed/delivery_method_generator.rb +19 -0
- data/lib/generators/noticed/model_generator.rb +56 -0
- data/lib/generators/noticed/notification_generator.rb +19 -0
- data/lib/generators/noticed/templates/README +7 -0
- data/lib/generators/noticed/templates/delivery_method.rb.tt +12 -0
- data/lib/generators/noticed/templates/notification.rb.tt +27 -0
- data/lib/noticed/base.rb +58 -23
- data/lib/noticed/coder.rb +2 -0
- data/lib/noticed/delivery_methods/action_cable.rb +12 -4
- data/lib/noticed/delivery_methods/base.rb +72 -9
- data/lib/noticed/delivery_methods/database.rb +13 -2
- data/lib/noticed/delivery_methods/email.rb +14 -1
- data/lib/noticed/delivery_methods/microsoft_teams.rb +32 -0
- data/lib/noticed/delivery_methods/slack.rb +2 -2
- data/lib/noticed/delivery_methods/test.rb +6 -0
- data/lib/noticed/delivery_methods/twilio.rb +1 -1
- data/lib/noticed/delivery_methods/vonage.rb +7 -1
- data/lib/noticed/model.rb +61 -0
- data/lib/noticed/text_coder.rb +16 -0
- data/lib/noticed/translation.rb +23 -0
- data/lib/noticed/version.rb +1 -1
- data/lib/noticed.rb +14 -0
- metadata +32 -8
- /data/{app/channels → lib}/noticed/notification_channel.rb +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5b998072ed72c9844842d8610a9ffcea75cf16f958296aa3d53e1a3c050b6db
|
|
4
|
+
data.tar.gz: 589f43985b3dc7740977730d10917d0b111706fe56c4daafedbacc08e7f2ce84
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f4a336ed688008a5abc3f91099a5ecc4128361beffd216e0e2e0bc0a1670286e607577d2f4ce13f1e36c2fb2fff3d93fbab9a10914d0321a2d1e0c2449ea715
|
|
7
|
+
data.tar.gz: b4a67b79dcf34892dcd11b56ad83e2c393a2da49c3eb38e3e911411164b4150ec27a836e53d1d7875ea40141276a398878e8c23304c326287299b26bafebacba
|
data/README.md
CHANGED
|
@@ -1,74 +1,183 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1>Noticed</h1>
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
### 🎉 Notifications for your Ruby on Rails app.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/excid3/noticed/actions) [](https://badge.fury.io/rb/noticed)
|
|
4
8
|
|
|
5
9
|
Currently, we support these notification delivery methods out of the box:
|
|
6
10
|
|
|
7
11
|
* Database
|
|
8
12
|
* Email
|
|
9
|
-
*
|
|
13
|
+
* ActionCable channels
|
|
14
|
+
* Slack
|
|
15
|
+
* Microsoft Teams
|
|
10
16
|
* Twilio (SMS)
|
|
11
17
|
* Vonage / Nexmo (SMS)
|
|
12
18
|
|
|
13
19
|
And you can easily add new notification types for any other delivery methods.
|
|
14
20
|
|
|
15
|
-
##
|
|
16
|
-
|
|
21
|
+
## 🎬 Screencast
|
|
22
|
+
|
|
23
|
+
<div style="width:50%">
|
|
24
|
+
<a href="https://www.youtube.com/watch?v=Scffi4otlFc"><img src="https://i.imgur.com/UvVKWwD.png" title="How to add Notifications to Rails with Noticed" /></a>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
[Watch Screencast](https://www.youtube.com/watch?v=Scffi4otlFc)
|
|
28
|
+
|
|
29
|
+
## 🚀 Installation
|
|
30
|
+
Run the following command to add Noticed to your Gemfile
|
|
17
31
|
|
|
18
32
|
```ruby
|
|
19
|
-
|
|
33
|
+
bundle add "noticed"
|
|
20
34
|
```
|
|
21
35
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
36
|
+
To save notifications to your database, use the following command to generate a Notification model.
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
rails generate noticed:model
|
|
25
40
|
```
|
|
26
41
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
This will generate a Notification model and instructions for associating User models with the notifications table.
|
|
43
|
+
|
|
44
|
+
## 📝 Usage
|
|
45
|
+
|
|
46
|
+
To generate a notification object, simply run:
|
|
47
|
+
|
|
48
|
+
`rails generate noticed:notification CommentNotification`
|
|
49
|
+
|
|
50
|
+
#### Sending Notifications
|
|
51
|
+
|
|
52
|
+
To send a notification to a user:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
# Instantiate a new notification
|
|
56
|
+
notification = CommentNotification.with(comment: @comment)
|
|
57
|
+
|
|
58
|
+
# Deliver notification in background job
|
|
59
|
+
notification.deliver_later(@comment.post.author)
|
|
60
|
+
|
|
61
|
+
# Deliver notification immediately
|
|
62
|
+
notification.deliver(@comment.post.author)
|
|
63
|
+
|
|
64
|
+
# Deliver notification to multiple recipients
|
|
65
|
+
notification.deliver_later(User.all)
|
|
30
66
|
```
|
|
31
67
|
|
|
32
|
-
|
|
68
|
+
This will instantiate a new notification with the `comment` stored in the notification's params.
|
|
69
|
+
|
|
70
|
+
Each delivery method is able to transform this metadata that's best for the format. For example, the database may simply store the comment so it can be linked when rendering in the navbar. The websocket mechanism may transform this into a browser notification or insert it into the navbar.
|
|
71
|
+
|
|
72
|
+
#### Notification Objects
|
|
73
|
+
|
|
74
|
+
Notifications inherit from `Noticed::Base`. This provides all their functionality and allows them to be delivered.
|
|
33
75
|
|
|
34
|
-
|
|
76
|
+
To add delivery methods, simply `include` the module for the delivery methods you would like to use.
|
|
35
77
|
|
|
36
78
|
```ruby
|
|
37
79
|
class CommentNotification < Noticed::Base
|
|
38
80
|
deliver_by :database
|
|
39
81
|
deliver_by :action_cable
|
|
40
|
-
deliver_by :email, if: :email_notifications?
|
|
82
|
+
deliver_by :email, mailer: 'CommentMailer', if: :email_notifications?
|
|
83
|
+
|
|
84
|
+
# I18n helpers
|
|
85
|
+
def message
|
|
86
|
+
t(".message")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# URL helpers are accessible in notifications
|
|
90
|
+
# Don't forget to set your default_url_options so Rails knows how to generate urls
|
|
91
|
+
def url
|
|
92
|
+
post_path(params[:post])
|
|
93
|
+
end
|
|
41
94
|
|
|
42
95
|
def email_notifications?
|
|
43
96
|
!!recipient.preferences[:email]
|
|
44
97
|
end
|
|
98
|
+
|
|
99
|
+
after_deliver do
|
|
100
|
+
# Anything you want
|
|
101
|
+
end
|
|
45
102
|
end
|
|
46
103
|
```
|
|
47
104
|
|
|
48
|
-
|
|
105
|
+
**Shared Options**
|
|
106
|
+
|
|
107
|
+
* `if: :method_name` - Calls `method_name`and cancels delivery method if `false` is returned
|
|
108
|
+
* `unless: :method_name` - Calls `method_name`and cancels delivery method if `true` is returned
|
|
109
|
+
* `delay: ActiveSupport::Duration` - Delays the delivery for the given duration of time
|
|
110
|
+
|
|
111
|
+
##### Helper Methods
|
|
112
|
+
|
|
113
|
+
You can define helper methods inside your Notification object to make it easier to render.
|
|
114
|
+
|
|
115
|
+
##### URL Helpers
|
|
116
|
+
|
|
117
|
+
Rails url helpers are included in notification classes by default so you have full access to them just like you would in your controllers and views.
|
|
118
|
+
|
|
119
|
+
Don't forget, you'll need to configure `default_url_options` in order for Rails to know what host and port to use when generating URLs.
|
|
49
120
|
|
|
50
121
|
```ruby
|
|
51
|
-
|
|
122
|
+
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
|
|
123
|
+
```
|
|
52
124
|
|
|
53
|
-
|
|
54
|
-
notification.deliver_later(@comment.post.author)
|
|
125
|
+
**Callbacks**
|
|
55
126
|
|
|
56
|
-
|
|
57
|
-
|
|
127
|
+
Like ActiveRecord, notifications have several different types of callbacks.
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
class CommentNotification < Noticed::Base
|
|
131
|
+
deliver_by :database
|
|
132
|
+
deliver_by :email, mailer: 'CommentMailer'
|
|
133
|
+
|
|
134
|
+
# Callbacks for the entire delivery
|
|
135
|
+
before_deliver :whatever
|
|
136
|
+
around_deliver :whatever
|
|
137
|
+
after_deliver :whatever
|
|
138
|
+
|
|
139
|
+
# Callbacks for each delivery method
|
|
140
|
+
before_database :whatever
|
|
141
|
+
around_database :whatever
|
|
142
|
+
after_database :whatever
|
|
143
|
+
|
|
144
|
+
before_email :whatever
|
|
145
|
+
around_email :whatever
|
|
146
|
+
after_email :whatever
|
|
147
|
+
end
|
|
58
148
|
```
|
|
59
149
|
|
|
60
|
-
|
|
150
|
+
When using `deliver_later` callbacks will be run around queuing the delivery method jobs (not inside the jobs as they actually execute).
|
|
61
151
|
|
|
62
|
-
|
|
152
|
+
Defining custom delivery methods allows you to add callbacks that run inside the background job as each individual delivery is executed. See the Custom Delivery Methods section for more information.
|
|
63
153
|
|
|
64
|
-
|
|
154
|
+
##### Translations
|
|
65
155
|
|
|
66
|
-
|
|
67
|
-
|
|
156
|
+
We've added `translate` and `t` helpers like Rails has to provide an easy way of scoping translations. If the key starts with a period, it will automatically scope the key under `notifications` and the underscored name of the notification class it is used in.
|
|
157
|
+
|
|
158
|
+
For example:
|
|
159
|
+
|
|
160
|
+
`t(".message")` looks up `en.notifications.new_comment.message`
|
|
161
|
+
|
|
162
|
+
##### User Preferences
|
|
163
|
+
|
|
164
|
+
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.
|
|
165
|
+
|
|
166
|
+
For example:
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
class CommentNotification < Noticed::Base
|
|
170
|
+
deliver_by :email, mailer: 'CommentMailer', if: :email_notifications?
|
|
171
|
+
|
|
172
|
+
def email_notifications?
|
|
173
|
+
recipient.email_notifications?
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
```
|
|
68
177
|
|
|
69
|
-
## Delivery Methods
|
|
178
|
+
## 🚛 Delivery Methods
|
|
70
179
|
|
|
71
|
-
The delivery methods are designed to be
|
|
180
|
+
The delivery methods are designed to be modular so you can customize the way each type gets delivered.
|
|
72
181
|
|
|
73
182
|
For example, emails will require a subject, body, and email address while an SMS requires a phone number and simple message. You can define the formats for each of these in your Notification and the delivery method will handle the processing of it.
|
|
74
183
|
|
|
@@ -78,7 +187,17 @@ Writes notification to the database.
|
|
|
78
187
|
|
|
79
188
|
`deliver_by :database`
|
|
80
189
|
|
|
81
|
-
**Note:** Database notifications are special in that they will run before the other delivery methods. We do this so you can reference the database record ID in other delivery methods.
|
|
190
|
+
**Note:** Database notifications are special in that they will run before the other delivery methods. We do this so you can reference the database record ID in other delivery methods. For that same reason, the delivery can't be delayed (via the `delay` option) or an error will be raised.
|
|
191
|
+
|
|
192
|
+
##### Options
|
|
193
|
+
|
|
194
|
+
* `association` - *Optional*
|
|
195
|
+
|
|
196
|
+
The name of the database association to use. Defaults to `:notifications`
|
|
197
|
+
|
|
198
|
+
* `format: :format_for_database` - *Optional*
|
|
199
|
+
|
|
200
|
+
Use a custom method to define the attributes saved to the database
|
|
82
201
|
|
|
83
202
|
### Email
|
|
84
203
|
|
|
@@ -86,7 +205,7 @@ Sends an email notification. Emails will always be sent with `deliver_later`
|
|
|
86
205
|
|
|
87
206
|
`deliver_by :email, mailer: "UserMailer"`
|
|
88
207
|
|
|
89
|
-
|
|
208
|
+
##### Options
|
|
90
209
|
|
|
91
210
|
* `mailer` - **Required**
|
|
92
211
|
|
|
@@ -96,13 +215,17 @@ Sends an email notification. Emails will always be sent with `deliver_later`
|
|
|
96
215
|
|
|
97
216
|
Used to customize the method on the mailer that is called
|
|
98
217
|
|
|
218
|
+
* `format: :format_for_email` - *Optional*
|
|
219
|
+
|
|
220
|
+
Use a custom method to define the params sent to the mailer. `recipient` will be merged into the params.
|
|
221
|
+
|
|
99
222
|
### ActionCable
|
|
100
223
|
|
|
101
224
|
Sends a notification to the browser via websockets (ActionCable channel by default).
|
|
102
225
|
|
|
103
226
|
`deliver_by :action_cable`
|
|
104
227
|
|
|
105
|
-
|
|
228
|
+
##### Options
|
|
106
229
|
|
|
107
230
|
* `format: :format_for_action_cable` - *Optional*
|
|
108
231
|
|
|
@@ -120,7 +243,7 @@ Sends a Slack notification via webhook.
|
|
|
120
243
|
|
|
121
244
|
`deliver_by :slack`
|
|
122
245
|
|
|
123
|
-
|
|
246
|
+
##### Options
|
|
124
247
|
|
|
125
248
|
* `format: :format_for_slack` - *Optional*
|
|
126
249
|
|
|
@@ -132,17 +255,53 @@ Sends a Slack notification via webhook.
|
|
|
132
255
|
|
|
133
256
|
Defaults to `Rails.application.credentials.slack[:notification_url]`
|
|
134
257
|
|
|
258
|
+
### Microsoft Teams
|
|
259
|
+
|
|
260
|
+
Sends a Teams notification via webhook.
|
|
261
|
+
|
|
262
|
+
`deliver_by :microsoft_teams`
|
|
263
|
+
|
|
264
|
+
#### Options
|
|
265
|
+
|
|
266
|
+
* `format: :format_for_teams` - *Optional*
|
|
267
|
+
|
|
268
|
+
Use a custom method to define the payload sent to slack. Method should return a Hash.
|
|
269
|
+
Documentation for posting via Webhooks available at: https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
{
|
|
273
|
+
title: "This is the title for the card",
|
|
274
|
+
text: "This is the body text for the card",
|
|
275
|
+
sections: [{activityTitle: "Section Title", activityText: "Section Text"}],
|
|
276
|
+
"potentialAction": [{
|
|
277
|
+
"@type": "OpenUri",
|
|
278
|
+
name: "Button Text",
|
|
279
|
+
targets: [{
|
|
280
|
+
os: "default",
|
|
281
|
+
uri: "https://example.com/foo/action"
|
|
282
|
+
}]
|
|
283
|
+
}]
|
|
284
|
+
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
* `url: :url_for_teams_channel`: - *Optional*
|
|
289
|
+
|
|
290
|
+
Use a custom method to retrieve the MS Teams Webhook URL. Method should return a string.
|
|
291
|
+
|
|
292
|
+
Defaults to `Rails.application.credentials.microsoft_teams[:notification_url]`
|
|
293
|
+
|
|
135
294
|
### Twilio SMS
|
|
136
295
|
|
|
137
296
|
Sends an SMS notification via Twilio.
|
|
138
297
|
|
|
139
298
|
`deliver_by :twilio`
|
|
140
299
|
|
|
141
|
-
|
|
300
|
+
##### Options
|
|
142
301
|
|
|
143
302
|
* `credentials: :get_twilio_credentials` - *Optional*
|
|
144
303
|
|
|
145
|
-
Use a custom method to retrieve the credentials for Twilio. Method should return a Hash with `:account_sid`, `:auth_token` and `:
|
|
304
|
+
Use a custom method to retrieve the credentials for Twilio. Method should return a Hash with `:account_sid`, `:auth_token` and `:phone_number` keys.
|
|
146
305
|
|
|
147
306
|
Defaults to `Rails.application.credentials.twilio[:account_sid]` and `Rails.application.credentials.twilio[:auth_token]`
|
|
148
307
|
|
|
@@ -168,11 +327,11 @@ Sends an SMS notification via Twilio.
|
|
|
168
327
|
|
|
169
328
|
### Vonage SMS
|
|
170
329
|
|
|
171
|
-
Sends an SMS notification
|
|
330
|
+
Sends an SMS notification via Vonage / Nexmo.
|
|
172
331
|
|
|
173
332
|
`deliver_by :vonage`
|
|
174
333
|
|
|
175
|
-
|
|
334
|
+
##### Options
|
|
176
335
|
|
|
177
336
|
* `credentials: :get_credentials` - *Optional*
|
|
178
337
|
|
|
@@ -195,65 +354,210 @@ Sends an SMS notification vai Vonage / Nexmo.
|
|
|
195
354
|
}
|
|
196
355
|
```
|
|
197
356
|
|
|
198
|
-
###
|
|
357
|
+
### 🚚 Custom Delivery Methods
|
|
199
358
|
|
|
200
|
-
|
|
359
|
+
To generate a custom delivery method, simply run
|
|
201
360
|
|
|
202
|
-
|
|
361
|
+
`rails generate noticed:delivery_method Discord`
|
|
203
362
|
|
|
204
|
-
|
|
205
|
-
class CommentNotification < Noticed::Base
|
|
206
|
-
deliver_by :email, if: :email_notifications?
|
|
363
|
+
This will generate a new `DeliveryMethods::Discord` class inside the `app/notifications/delivery_methods` folder, which can be used to deliver notifications to Discord.
|
|
207
364
|
|
|
208
|
-
|
|
209
|
-
|
|
365
|
+
```ruby
|
|
366
|
+
class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
|
|
367
|
+
def deliver
|
|
368
|
+
# Logic for sending a Discord notification
|
|
210
369
|
end
|
|
211
370
|
end
|
|
212
371
|
```
|
|
213
372
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
You can define a custom delivery method easily by adding a `deliver_by` line with a unique name and class option. The class will be instantiated and should inherit from `Noticed::DeliveryMethods::Base`.
|
|
373
|
+
You can use the custom delivery method thus created by adding a `deliver_by` line with a unique name and `class` option in your notification class.
|
|
217
374
|
|
|
218
375
|
```ruby
|
|
219
376
|
class MyNotification < Noticed::Base
|
|
220
|
-
deliver_by :discord, class: "
|
|
377
|
+
deliver_by :discord, class: "DeliveryMethods::Discord"
|
|
221
378
|
end
|
|
222
379
|
```
|
|
223
380
|
|
|
381
|
+
Delivery methods have access to the following methods and attributes:
|
|
382
|
+
|
|
383
|
+
* `notification` - The instance of the Notification. You can call methods on the notification to let the user easily override formatting and other functionality of the delivery method.
|
|
384
|
+
* `options` - Any configuration options on the `deliver_by` line.
|
|
385
|
+
* `recipient` - The object who should receive the notification. This is typically a User, Account, or other ActiveRecord model.
|
|
386
|
+
* `params` - The params passed into the notification. This is details about the event that happened. For example, a user commenting on a post would have params of `{ user: User.first }`
|
|
387
|
+
|
|
388
|
+
#### Validating options passed to Custom Delivery methods
|
|
389
|
+
|
|
390
|
+
The presence of the delivery method options is automatically validated if using the `option(s)` method.
|
|
391
|
+
|
|
392
|
+
If you want to validate that the passed options contain valid values, or to add any custom validations, override the `self.validate!(delivery_method_options)` method from the `Noticed::DeliveryMethods::Base` class.
|
|
393
|
+
|
|
224
394
|
```ruby
|
|
225
|
-
class
|
|
395
|
+
class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
|
|
396
|
+
option :username # Requires the username option to be passed
|
|
397
|
+
|
|
226
398
|
def deliver
|
|
227
399
|
# Logic for sending a Discord notification
|
|
228
400
|
end
|
|
401
|
+
|
|
402
|
+
def self.validate!(delivery_method_options)
|
|
403
|
+
super # Don't forget to call super, otherwise option presence won't be validated
|
|
404
|
+
|
|
405
|
+
# Custom validations
|
|
406
|
+
if delivery_method_options[:username].blank?
|
|
407
|
+
raise Noticed::ValidationError, 'the `username` option must be present'
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
class CommentNotification < Noticed::Base
|
|
413
|
+
deliver_by :discord, class: 'DeliveryMethods::Discord'
|
|
229
414
|
end
|
|
230
415
|
```
|
|
231
416
|
|
|
232
|
-
|
|
417
|
+
Now it will raise an error because a required argument is missing.
|
|
233
418
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
419
|
+
To fix the error, the argument has to be passed correctly. For example:
|
|
420
|
+
|
|
421
|
+
```ruby
|
|
422
|
+
class CommentNotification < Noticed::Base
|
|
423
|
+
deliver_by :discord, class: 'DeliveryMethods::Discord', username: User.admin.username
|
|
424
|
+
end
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
#### Callbacks
|
|
428
|
+
|
|
429
|
+
Callbacks for delivery methods wrap the *actual* delivery of the notification. You can use `before_deliver`, `around_deliver` and `after_deliver` in your custom delivery methods.
|
|
430
|
+
|
|
431
|
+
```ruby
|
|
432
|
+
class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
|
|
433
|
+
after_deliver do
|
|
434
|
+
# Do whatever you want
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
```
|
|
238
438
|
|
|
239
439
|
#### Limitations
|
|
240
440
|
|
|
241
441
|
Rails 6.1+ can serialize Class and Module objects as arguments to ActiveJob. The following syntax should work for Rails 6.1+:
|
|
242
442
|
|
|
243
443
|
```ruby
|
|
244
|
-
deliver_by
|
|
444
|
+
deliver_by DeliveryMethods::Discord
|
|
245
445
|
```
|
|
246
446
|
|
|
247
|
-
For Rails 6.0
|
|
447
|
+
For Rails 6.0, you must pass strings of the class names in the `deliver_by` options.
|
|
248
448
|
|
|
249
449
|
```ruby
|
|
250
|
-
deliver_by :discord, class: "
|
|
450
|
+
deliver_by :discord, class: "DeliveryMethods::Discord"
|
|
251
451
|
```
|
|
252
452
|
|
|
253
453
|
We recommend the Rails 6.0 compatible options to prevent confusion.
|
|
254
454
|
|
|
255
|
-
|
|
256
|
-
|
|
455
|
+
### 📦 Database Model
|
|
456
|
+
|
|
457
|
+
The Notification database model includes several helpful features to make working with database notifications easier.
|
|
458
|
+
|
|
459
|
+
#### Class methods
|
|
460
|
+
|
|
461
|
+
Sorting notifications by newest first:
|
|
462
|
+
|
|
463
|
+
```ruby
|
|
464
|
+
user.notifications.newest_first
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Query for read or unread notifications:
|
|
468
|
+
|
|
469
|
+
```ruby
|
|
470
|
+
user.notifications.read
|
|
471
|
+
user.notifications.unread
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
Marking all notifications as read or unread:
|
|
476
|
+
|
|
477
|
+
```ruby
|
|
478
|
+
user.notifications.mark_as_read!
|
|
479
|
+
user.notifications.mark_as_unread!
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
#### Instance methods
|
|
483
|
+
|
|
484
|
+
Convert back into a Noticed notification object:
|
|
485
|
+
|
|
486
|
+
```ruby
|
|
487
|
+
@notification.to_notification
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Mark notification as read / unread:
|
|
491
|
+
|
|
492
|
+
```ruby
|
|
493
|
+
@notification.mark_as_read!
|
|
494
|
+
@notification.mark_as_unread!
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Check if read / unread:
|
|
498
|
+
|
|
499
|
+
```ruby
|
|
500
|
+
@notification.read?
|
|
501
|
+
@notification.unread?
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
#### Associating Notifications
|
|
505
|
+
|
|
506
|
+
Adding notification associations to your models makes querying and deleting notifications easy and is a pretty critical feature of most applications.
|
|
507
|
+
|
|
508
|
+
For example, in most cases, you'll want to delete notifications for records that are destroyed.
|
|
509
|
+
|
|
510
|
+
##### JSON Columns
|
|
511
|
+
|
|
512
|
+
If you're using MySQL or Postgresql, the `params` column on the notifications table is in `json` or `jsonb` format and can be queried against directly.
|
|
513
|
+
|
|
514
|
+
For example, we can query the notifications and delete them on destroy like so:
|
|
515
|
+
|
|
516
|
+
```ruby
|
|
517
|
+
class Post < ApplicationRecord
|
|
518
|
+
def notifications
|
|
519
|
+
# Exact match
|
|
520
|
+
@notifications ||= Notification.where(params: { post: self })
|
|
521
|
+
|
|
522
|
+
# Or Postgres syntax to query the post key in the JSON column
|
|
523
|
+
# @notifications ||= Notification.where("params->'post' = ?", Noticed::Coder.dump(self).to_json)
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
before_destroy :destroy_notifications
|
|
527
|
+
|
|
528
|
+
def destroy_notifications
|
|
529
|
+
notifications.destroy_all
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
##### Polymorphic Association
|
|
535
|
+
|
|
536
|
+
If your notification is only associated with one model or you're using a `text` column for your params column , then a polymorphic association is what you'll want to use.
|
|
537
|
+
|
|
538
|
+
1. Add a polymorphic association to the Notification model. `rails g migration AddNotifiableToNotifications notifiable:belongs_to{polymorphic}`
|
|
539
|
+
|
|
540
|
+
2. Add `has_many :notifications, as: :notifiable, dependent: :destroy` to each model
|
|
541
|
+
|
|
542
|
+
3. Customize database `format: ` option to write the `notifiable` attribute(s) when saving the notification
|
|
543
|
+
|
|
544
|
+
```ruby
|
|
545
|
+
class ExampleNotification < Noticed::Base
|
|
546
|
+
deliver_by :database, format: :format_for_database
|
|
547
|
+
|
|
548
|
+
def format_for_database
|
|
549
|
+
{
|
|
550
|
+
notifiable: params.delete(:post),
|
|
551
|
+
type: self.class.name,
|
|
552
|
+
params: params
|
|
553
|
+
}
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
## 🙏 Contributing
|
|
559
|
+
|
|
560
|
+
This project uses [Standard](https://github.com/testdouble/standard) for formatting Ruby code. Please make sure to run `standardrb` before submitting pull requests.
|
|
257
561
|
|
|
258
|
-
## License
|
|
562
|
+
## 📝 License
|
|
259
563
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
|
@@ -18,6 +18,10 @@ require "bundler/gem_tasks"
|
|
|
18
18
|
|
|
19
19
|
require "rake/testtask"
|
|
20
20
|
|
|
21
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
|
22
|
+
load "rails/tasks/engine.rake"
|
|
23
|
+
load "rails/tasks/statistics.rake"
|
|
24
|
+
|
|
21
25
|
Rake::TestTask.new(:test) do |t|
|
|
22
26
|
t.libs << "test"
|
|
23
27
|
t.pattern = "test/**/*_test.rb"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators/named_base"
|
|
4
|
+
|
|
5
|
+
module Noticed
|
|
6
|
+
module Generators
|
|
7
|
+
class DeliveryMethodGenerator < Rails::Generators::NamedBase
|
|
8
|
+
include Rails::Generators::ResourceHelpers
|
|
9
|
+
|
|
10
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
11
|
+
|
|
12
|
+
desc "Generates a class for a custom delivery method with the given NAME."
|
|
13
|
+
|
|
14
|
+
def generate_notification
|
|
15
|
+
template "delivery_method.rb", "app/notifications/delivery_methods/#{singular_name}.rb"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators/named_base"
|
|
4
|
+
|
|
5
|
+
module Noticed
|
|
6
|
+
module Generators
|
|
7
|
+
class ModelGenerator < Rails::Generators::NamedBase
|
|
8
|
+
include Rails::Generators::ResourceHelpers
|
|
9
|
+
|
|
10
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
11
|
+
|
|
12
|
+
desc "Generates a Notification model for storing notifications."
|
|
13
|
+
|
|
14
|
+
argument :name, type: :string, default: "Notification", banner: "Notification"
|
|
15
|
+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
|
16
|
+
|
|
17
|
+
def generate_notification
|
|
18
|
+
generate :model, name, "recipient:references{polymorphic}", "type", params_column, "read_at:datetime:index", *attributes
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_noticed_model
|
|
22
|
+
inject_into_class model_path, class_name, " include Noticed::Model\n"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_not_nullable
|
|
26
|
+
migration_path = Dir.glob(Rails.root.join("db/migrate/*")).max_by { |f| File.mtime(f) }
|
|
27
|
+
|
|
28
|
+
# Force is required because null: false already exists in the file and Thor isn't smart enough to tell the difference
|
|
29
|
+
insert_into_file migration_path, after: "t.string :type", force: true do
|
|
30
|
+
", null: false"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def done
|
|
35
|
+
readme "README" if behavior == :invoke
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def model_path
|
|
41
|
+
@model_path ||= File.join("app", "models", "#{file_path}.rb")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def params_column
|
|
45
|
+
case ActiveRecord::Base.configurations.configs_for(spec_name: "primary").config["adapter"]
|
|
46
|
+
when "mysql2"
|
|
47
|
+
"params:json"
|
|
48
|
+
when "postgresql"
|
|
49
|
+
"params:jsonb"
|
|
50
|
+
else
|
|
51
|
+
"params:text"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|