noticed 1.2.5 → 1.3.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/README.md +187 -16
- data/Rakefile +4 -0
- data/lib/generators/noticed/delivery_method_generator.rb +19 -0
- data/lib/generators/noticed/model_generator.rb +20 -1
- data/lib/generators/noticed/notification_generator.rb +1 -1
- data/lib/generators/noticed/templates/delivery_method.rb.tt +12 -0
- data/lib/noticed/base.rb +33 -11
- data/lib/noticed/coder.rb +2 -2
- data/lib/noticed/delivery_methods/action_cable.rb +12 -4
- data/lib/noticed/delivery_methods/base.rb +65 -8
- data/lib/noticed/delivery_methods/database.rb +7 -0
- data/lib/noticed/delivery_methods/email.rb +6 -6
- data/lib/noticed/delivery_methods/microsoft_teams.rb +32 -0
- data/lib/noticed/delivery_methods/slack.rb +2 -2
- data/lib/noticed/delivery_methods/twilio.rb +1 -1
- data/lib/noticed/delivery_methods/vonage.rb +7 -1
- data/lib/noticed/engine.rb +5 -0
- data/lib/noticed/has_notifications.rb +32 -0
- data/lib/noticed/model.rb +25 -6
- data/lib/noticed/text_coder.rb +16 -0
- data/lib/noticed/translation.rb +17 -15
- data/lib/noticed/version.rb +1 -1
- data/lib/noticed.rb +12 -0
- metadata +41 -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: 83635d722a21df622c90c4e8ded293206242be768b30b2139c41f13bc4d6712c
|
|
4
|
+
data.tar.gz: 707ff4e0e8d09ed4c1fa1b0a7228353de637b070e849e7eb234b58b6fb491e40
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85ddb6e11858df2b21b4dc098096c78465f7ac3dcb7a804037f3cf1855735b954cccb1cb0ad3227d1ebd89cb98e2e6e5d0138af27e73e52d2feeb35ac85ccdec
|
|
7
|
+
data.tar.gz: 80d3485a086e8203397f83bf3269e057ec63c9da89b3016d29a8395499447419336d89e7d01daff911a838159b963423dd45f6161b80c0dfab608f2f4e11c662
|
data/README.md
CHANGED
|
@@ -12,6 +12,7 @@ Currently, we support these notification delivery methods out of the box:
|
|
|
12
12
|
* Email
|
|
13
13
|
* ActionCable channels
|
|
14
14
|
* Slack
|
|
15
|
+
* Microsoft Teams
|
|
15
16
|
* Twilio (SMS)
|
|
16
17
|
* Vonage / Nexmo (SMS)
|
|
17
18
|
|
|
@@ -78,7 +79,7 @@ To add delivery methods, simply `include` the module for the delivery methods yo
|
|
|
78
79
|
class CommentNotification < Noticed::Base
|
|
79
80
|
deliver_by :database
|
|
80
81
|
deliver_by :action_cable
|
|
81
|
-
deliver_by :email, if: :email_notifications?
|
|
82
|
+
deliver_by :email, mailer: 'CommentMailer', if: :email_notifications?
|
|
82
83
|
|
|
83
84
|
# I18n helpers
|
|
84
85
|
def message
|
|
@@ -86,6 +87,7 @@ class CommentNotification < Noticed::Base
|
|
|
86
87
|
end
|
|
87
88
|
|
|
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
|
|
89
91
|
def url
|
|
90
92
|
post_path(params[:post])
|
|
91
93
|
end
|
|
@@ -104,6 +106,7 @@ end
|
|
|
104
106
|
|
|
105
107
|
* `if: :method_name` - Calls `method_name`and cancels delivery method if `false` is returned
|
|
106
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
|
|
107
110
|
|
|
108
111
|
##### Helper Methods
|
|
109
112
|
|
|
@@ -113,6 +116,12 @@ You can define helper methods inside your Notification object to make it easier
|
|
|
113
116
|
|
|
114
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.
|
|
115
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.
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
|
|
123
|
+
```
|
|
124
|
+
|
|
116
125
|
**Callbacks**
|
|
117
126
|
|
|
118
127
|
Like ActiveRecord, notifications have several different types of callbacks.
|
|
@@ -120,7 +129,7 @@ Like ActiveRecord, notifications have several different types of callbacks.
|
|
|
120
129
|
```ruby
|
|
121
130
|
class CommentNotification < Noticed::Base
|
|
122
131
|
deliver_by :database
|
|
123
|
-
deliver_by :email
|
|
132
|
+
deliver_by :email, mailer: 'CommentMailer'
|
|
124
133
|
|
|
125
134
|
# Callbacks for the entire delivery
|
|
126
135
|
before_deliver :whatever
|
|
@@ -158,7 +167,7 @@ For example:
|
|
|
158
167
|
|
|
159
168
|
```ruby
|
|
160
169
|
class CommentNotification < Noticed::Base
|
|
161
|
-
deliver_by :email, if: :email_notifications?
|
|
170
|
+
deliver_by :email, mailer: 'CommentMailer', if: :email_notifications?
|
|
162
171
|
|
|
163
172
|
def email_notifications?
|
|
164
173
|
recipient.email_notifications?
|
|
@@ -178,7 +187,7 @@ Writes notification to the database.
|
|
|
178
187
|
|
|
179
188
|
`deliver_by :database`
|
|
180
189
|
|
|
181
|
-
**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.
|
|
182
191
|
|
|
183
192
|
##### Options
|
|
184
193
|
|
|
@@ -246,6 +255,42 @@ Sends a Slack notification via webhook.
|
|
|
246
255
|
|
|
247
256
|
Defaults to `Rails.application.credentials.slack[:notification_url]`
|
|
248
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 Microsoft Teams. 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
|
+
|
|
249
294
|
### Twilio SMS
|
|
250
295
|
|
|
251
296
|
Sends an SMS notification via Twilio.
|
|
@@ -256,7 +301,7 @@ Sends an SMS notification via Twilio.
|
|
|
256
301
|
|
|
257
302
|
* `credentials: :get_twilio_credentials` - *Optional*
|
|
258
303
|
|
|
259
|
-
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.
|
|
260
305
|
|
|
261
306
|
Defaults to `Rails.application.credentials.twilio[:account_sid]` and `Rails.application.credentials.twilio[:auth_token]`
|
|
262
307
|
|
|
@@ -309,24 +354,57 @@ Sends an SMS notification via Vonage / Nexmo.
|
|
|
309
354
|
}
|
|
310
355
|
```
|
|
311
356
|
|
|
312
|
-
###
|
|
357
|
+
### Fallback Notifications
|
|
313
358
|
|
|
314
|
-
|
|
359
|
+
A common pattern is to deliver a notification via the database and 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 `delay` option, and the conditional `if` / `unless` option.
|
|
315
360
|
|
|
316
361
|
```ruby
|
|
317
|
-
class
|
|
318
|
-
deliver_by :
|
|
362
|
+
class CommentNotification < Noticed::Base
|
|
363
|
+
deliver_by :database
|
|
364
|
+
deliver_by :email, mailer: 'CommentMailer', delay: 15.minutes, unless: :read?
|
|
319
365
|
end
|
|
320
366
|
```
|
|
321
367
|
|
|
368
|
+
Here a notification will be created immediately in the database (for display directly in your app). If the notification has not been read after 15 minutes, the email notification will be sent. If the notification has already been read in the app, the email will be skipped.
|
|
369
|
+
|
|
370
|
+
You can also configure multiple fallback options:
|
|
371
|
+
|
|
322
372
|
```ruby
|
|
323
|
-
class
|
|
373
|
+
class CriticalSystemNotification < Noticed::Base
|
|
374
|
+
deliver_by :slack
|
|
375
|
+
deliver_by :email, mailer: 'CriticalSystemMailer', delay: 10.minutes, unless: :read?
|
|
376
|
+
deliver_by :twilio, delay: 20.minutes, unless: :read?
|
|
377
|
+
end
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
In this scenario, you can create an escalating notification that starts with a ping in Slack, then emails the team, and then finally sends an SMS to the on-call phone.
|
|
381
|
+
|
|
382
|
+
You can mix and match the options and delivery methods to suit your application specific needs.
|
|
383
|
+
|
|
384
|
+
### 🚚 Custom Delivery Methods
|
|
385
|
+
|
|
386
|
+
To generate a custom delivery method, simply run
|
|
387
|
+
|
|
388
|
+
`rails generate noticed:delivery_method Discord`
|
|
389
|
+
|
|
390
|
+
This will generate a new `DeliveryMethods::Discord` class inside the `app/notifications/delivery_methods` folder, which can be used to deliver notifications to Discord.
|
|
391
|
+
|
|
392
|
+
```ruby
|
|
393
|
+
class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
|
|
324
394
|
def deliver
|
|
325
395
|
# Logic for sending a Discord notification
|
|
326
396
|
end
|
|
327
397
|
end
|
|
328
398
|
```
|
|
329
399
|
|
|
400
|
+
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.
|
|
401
|
+
|
|
402
|
+
```ruby
|
|
403
|
+
class MyNotification < Noticed::Base
|
|
404
|
+
deliver_by :discord, class: "DeliveryMethods::Discord"
|
|
405
|
+
end
|
|
406
|
+
```
|
|
407
|
+
|
|
330
408
|
Delivery methods have access to the following methods and attributes:
|
|
331
409
|
|
|
332
410
|
* `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.
|
|
@@ -334,12 +412,51 @@ Delivery methods have access to the following methods and attributes:
|
|
|
334
412
|
* `recipient` - The object who should receive the notification. This is typically a User, Account, or other ActiveRecord model.
|
|
335
413
|
* `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 }`
|
|
336
414
|
|
|
415
|
+
#### Validating options passed to Custom Delivery methods
|
|
416
|
+
|
|
417
|
+
The presence of the delivery method options is automatically validated if using the `option(s)` method.
|
|
418
|
+
|
|
419
|
+
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.
|
|
420
|
+
|
|
421
|
+
```ruby
|
|
422
|
+
class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
|
|
423
|
+
option :username # Requires the username option to be passed
|
|
424
|
+
|
|
425
|
+
def deliver
|
|
426
|
+
# Logic for sending a Discord notification
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def self.validate!(delivery_method_options)
|
|
430
|
+
super # Don't forget to call super, otherwise option presence won't be validated
|
|
431
|
+
|
|
432
|
+
# Custom validations
|
|
433
|
+
if delivery_method_options[:username].blank?
|
|
434
|
+
raise Noticed::ValidationError, 'the `username` option must be present'
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
class CommentNotification < Noticed::Base
|
|
440
|
+
deliver_by :discord, class: 'DeliveryMethods::Discord'
|
|
441
|
+
end
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Now it will raise an error because a required argument is missing.
|
|
445
|
+
|
|
446
|
+
To fix the error, the argument has to be passed correctly. For example:
|
|
447
|
+
|
|
448
|
+
```ruby
|
|
449
|
+
class CommentNotification < Noticed::Base
|
|
450
|
+
deliver_by :discord, class: 'DeliveryMethods::Discord', username: User.admin.username
|
|
451
|
+
end
|
|
452
|
+
```
|
|
453
|
+
|
|
337
454
|
#### Callbacks
|
|
338
455
|
|
|
339
456
|
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.
|
|
340
457
|
|
|
341
458
|
```ruby
|
|
342
|
-
class
|
|
459
|
+
class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
|
|
343
460
|
after_deliver do
|
|
344
461
|
# Do whatever you want
|
|
345
462
|
end
|
|
@@ -351,13 +468,13 @@ end
|
|
|
351
468
|
Rails 6.1+ can serialize Class and Module objects as arguments to ActiveJob. The following syntax should work for Rails 6.1+:
|
|
352
469
|
|
|
353
470
|
```ruby
|
|
354
|
-
deliver_by
|
|
471
|
+
deliver_by DeliveryMethods::Discord
|
|
355
472
|
```
|
|
356
473
|
|
|
357
|
-
For Rails 6.0
|
|
474
|
+
For Rails 6.0, you must pass strings of the class names in the `deliver_by` options.
|
|
358
475
|
|
|
359
476
|
```ruby
|
|
360
|
-
deliver_by :discord, class: "
|
|
477
|
+
deliver_by :discord, class: "DeliveryMethods::Discord"
|
|
361
478
|
```
|
|
362
479
|
|
|
363
480
|
We recommend the Rails 6.0 compatible options to prevent confusion.
|
|
@@ -374,10 +491,19 @@ Sorting notifications by newest first:
|
|
|
374
491
|
user.notifications.newest_first
|
|
375
492
|
```
|
|
376
493
|
|
|
377
|
-
|
|
494
|
+
Query for read or unread notifications:
|
|
495
|
+
|
|
496
|
+
```ruby
|
|
497
|
+
user.notifications.read
|
|
498
|
+
user.notifications.unread
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
Marking all notifications as read or unread:
|
|
378
503
|
|
|
379
504
|
```ruby
|
|
380
505
|
user.notifications.mark_as_read!
|
|
506
|
+
user.notifications.mark_as_unread!
|
|
381
507
|
```
|
|
382
508
|
|
|
383
509
|
#### Instance methods
|
|
@@ -388,10 +514,11 @@ Convert back into a Noticed notification object:
|
|
|
388
514
|
@notification.to_notification
|
|
389
515
|
```
|
|
390
516
|
|
|
391
|
-
Mark notification as read:
|
|
517
|
+
Mark notification as read / unread:
|
|
392
518
|
|
|
393
519
|
```ruby
|
|
394
520
|
@notification.mark_as_read!
|
|
521
|
+
@notification.mark_as_unread!
|
|
395
522
|
```
|
|
396
523
|
|
|
397
524
|
Check if read / unread:
|
|
@@ -401,6 +528,50 @@ Check if read / unread:
|
|
|
401
528
|
@notification.unread?
|
|
402
529
|
```
|
|
403
530
|
|
|
531
|
+
#### Associating Notifications
|
|
532
|
+
|
|
533
|
+
Adding notification associations to your models makes querying and deleting notifications easy and is a pretty critical feature of most applications.
|
|
534
|
+
|
|
535
|
+
For example, in most cases, you'll want to delete notifications for records that are destroyed.
|
|
536
|
+
|
|
537
|
+
We'll need two associations for this:
|
|
538
|
+
|
|
539
|
+
1. Notifications where the record is the recipient
|
|
540
|
+
2. Notifications where the record is in the notification params
|
|
541
|
+
|
|
542
|
+
For example, we can query the notifications and delete them on destroy like so:
|
|
543
|
+
|
|
544
|
+
```ruby
|
|
545
|
+
class Post < ApplicationRecord
|
|
546
|
+
# Standard association for deleting notifications when you're the recipient
|
|
547
|
+
has_many :notifications, as: :recipient, dependent: :destroy
|
|
548
|
+
|
|
549
|
+
# Helper for associating and destroying Notification records where(params: {post: self})
|
|
550
|
+
has_noticed_notifications
|
|
551
|
+
|
|
552
|
+
# You can override the param_name, the notification model name, or disable the before_destroy callback
|
|
553
|
+
has_noticed_notifications param_name: :parent, destroy: false, model: "Notification"
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
# Create a CommentNotification with a post param
|
|
557
|
+
CommentNotification.with(post: @post).deliver(user)
|
|
558
|
+
# Lookup Notifications where params: {post: @post}
|
|
559
|
+
@post.notifications_as_post
|
|
560
|
+
|
|
561
|
+
CommentNotification.with(parent: @post).deliver(user)
|
|
562
|
+
@post.notifications_as_parent
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
#### Handling Deleted Records
|
|
566
|
+
|
|
567
|
+
If you create a notification but delete the associated record and forgot `has_noticed_notifications` on the model, the jobs for sending the notification will not be able to find the record when ActiveJob deserializes. You can discord the job on these errors by adding the following to `ApplicationJob`:
|
|
568
|
+
|
|
569
|
+
```ruby
|
|
570
|
+
class ApplicationJob < ActiveJob::Base
|
|
571
|
+
discard_on ActiveJob::DeserializationError
|
|
572
|
+
end
|
|
573
|
+
```
|
|
574
|
+
|
|
404
575
|
## 🙏 Contributing
|
|
405
576
|
|
|
406
577
|
This project uses [Standard](https://github.com/testdouble/standard) for formatting Ruby code. Please make sure to run `standardrb` before submitting pull requests.
|
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
|
|
@@ -15,13 +15,22 @@ module Noticed
|
|
|
15
15
|
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
|
16
16
|
|
|
17
17
|
def generate_notification
|
|
18
|
-
generate :model, name, "recipient:references{polymorphic}", "type",
|
|
18
|
+
generate :model, name, "recipient:references{polymorphic}", "type", params_column, "read_at:datetime:index", *attributes
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def add_noticed_model
|
|
22
22
|
inject_into_class model_path, class_name, " include Noticed::Model\n"
|
|
23
23
|
end
|
|
24
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
|
+
|
|
25
34
|
def done
|
|
26
35
|
readme "README" if behavior == :invoke
|
|
27
36
|
end
|
|
@@ -31,6 +40,16 @@ module Noticed
|
|
|
31
40
|
def model_path
|
|
32
41
|
@model_path ||= File.join("app", "models", "#{file_path}.rb")
|
|
33
42
|
end
|
|
43
|
+
|
|
44
|
+
def params_column
|
|
45
|
+
case ActiveRecord::Base.configurations.configs_for(spec_name: "primary").config["adapter"]
|
|
46
|
+
when "postgresql"
|
|
47
|
+
"params:jsonb"
|
|
48
|
+
else
|
|
49
|
+
# MySQL and SQLite both support json
|
|
50
|
+
"params:json"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
34
53
|
end
|
|
35
54
|
end
|
|
36
55
|
end
|
|
@@ -12,7 +12,7 @@ module Noticed
|
|
|
12
12
|
desc "Generates a notification with the given NAME."
|
|
13
13
|
|
|
14
14
|
def generate_notification
|
|
15
|
-
template "notification.rb", "app/notifications/#{
|
|
15
|
+
template "notification.rb", "app/notifications/#{file_path}.rb"
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class DeliveryMethods::<%= class_name %> < Noticed::DeliveryMethods::Base
|
|
2
|
+
def deliver
|
|
3
|
+
# Logic for sending the notification
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
# You may override this method to validate options for the delivery method
|
|
7
|
+
# Invalid options should raise a ValidationError
|
|
8
|
+
#
|
|
9
|
+
# def self.validate!(options)
|
|
10
|
+
# raise ValidationError, "required_option missing" unless options[:required_option]
|
|
11
|
+
# end
|
|
12
|
+
end
|
data/lib/noticed/base.rb
CHANGED
|
@@ -12,6 +12,8 @@ module Noticed
|
|
|
12
12
|
# Gives notifications access to the record and recipient when formatting for delivery
|
|
13
13
|
attr_accessor :record, :recipient
|
|
14
14
|
|
|
15
|
+
delegate :read?, :unread?, to: :record
|
|
16
|
+
|
|
15
17
|
class << self
|
|
16
18
|
def deliver_by(name, options = {})
|
|
17
19
|
delivery_methods.push(name: name, options: options)
|
|
@@ -29,9 +31,10 @@ module Noticed
|
|
|
29
31
|
new(params)
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
def
|
|
33
|
-
param_names.
|
|
34
|
+
def params(*names)
|
|
35
|
+
param_names.concat Array.wrap(names)
|
|
34
36
|
end
|
|
37
|
+
alias_method :param, :params
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
def initialize(params = {})
|
|
@@ -68,6 +71,9 @@ module Noticed
|
|
|
68
71
|
def run_delivery(recipient, enqueue: true)
|
|
69
72
|
delivery_methods = self.class.delivery_methods.dup
|
|
70
73
|
|
|
74
|
+
# Set recipient to instance var so it is available to Notification class
|
|
75
|
+
@recipient = recipient
|
|
76
|
+
|
|
71
77
|
# Run database delivery inline first if it exists so other methods have access to the record
|
|
72
78
|
if (index = delivery_methods.find_index { |m| m[:name] == :database })
|
|
73
79
|
delivery_method = delivery_methods.delete_at(index)
|
|
@@ -81,9 +87,6 @@ module Noticed
|
|
|
81
87
|
|
|
82
88
|
# Actually runs an individual delivery
|
|
83
89
|
def run_delivery_method(delivery_method, recipient:, enqueue:)
|
|
84
|
-
return if (delivery_method_name = delivery_method.dig(:options, :if)) && !send(delivery_method_name)
|
|
85
|
-
return if (delivery_method_name = delivery_method.dig(:options, :unless)) && send(delivery_method_name)
|
|
86
|
-
|
|
87
90
|
args = {
|
|
88
91
|
notification_class: self.class.name,
|
|
89
92
|
options: delivery_method[:options],
|
|
@@ -93,27 +96,46 @@ module Noticed
|
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
run_callbacks delivery_method[:name] do
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
method = delivery_method_for(delivery_method[:name], delivery_method[:options])
|
|
100
|
+
|
|
101
|
+
# Always perfrom later if a delay is present
|
|
102
|
+
if (delay = delivery_method.dig(:options, :delay))
|
|
103
|
+
method.set(wait: delay).perform_later(args)
|
|
104
|
+
elsif enqueue
|
|
105
|
+
method.perform_later(args)
|
|
106
|
+
else
|
|
107
|
+
method.perform_now(args)
|
|
108
|
+
end
|
|
98
109
|
end
|
|
99
110
|
end
|
|
100
111
|
|
|
101
|
-
|
|
102
|
-
def get_class(name, options)
|
|
112
|
+
def delivery_method_for(name, options)
|
|
103
113
|
if options[:class]
|
|
104
114
|
options[:class].constantize
|
|
105
115
|
else
|
|
106
|
-
"Noticed::DeliveryMethods::#{name.to_s.
|
|
116
|
+
"Noticed::DeliveryMethods::#{name.to_s.camelize}".constantize
|
|
107
117
|
end
|
|
108
118
|
end
|
|
109
119
|
|
|
110
|
-
# Validates that all params are present
|
|
111
120
|
def validate!
|
|
121
|
+
validate_params_present!
|
|
122
|
+
validate_options_of_delivery_methods!
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Validates that all params are present
|
|
126
|
+
def validate_params_present!
|
|
112
127
|
self.class.param_names.each do |param_name|
|
|
113
128
|
if params[param_name].nil?
|
|
114
129
|
raise ValidationError, "#{param_name} is missing."
|
|
115
130
|
end
|
|
116
131
|
end
|
|
117
132
|
end
|
|
133
|
+
|
|
134
|
+
def validate_options_of_delivery_methods!
|
|
135
|
+
delivery_methods.each do |delivery_method|
|
|
136
|
+
method = delivery_method_for(delivery_method[:name], delivery_method[:options])
|
|
137
|
+
method.validate!(delivery_method[:options])
|
|
138
|
+
end
|
|
139
|
+
end
|
|
118
140
|
end
|
|
119
141
|
end
|
data/lib/noticed/coder.rb
CHANGED
|
@@ -2,12 +2,12 @@ module Noticed
|
|
|
2
2
|
class Coder
|
|
3
3
|
def self.load(data)
|
|
4
4
|
return if data.nil?
|
|
5
|
-
ActiveJob::Arguments.send(:deserialize_argument,
|
|
5
|
+
ActiveJob::Arguments.send(:deserialize_argument, data)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def self.dump(data)
|
|
9
9
|
return if data.nil?
|
|
10
|
-
ActiveJob::Arguments.send(:serialize_argument, data)
|
|
10
|
+
ActiveJob::Arguments.send(:serialize_argument, data)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -16,10 +16,18 @@ module Noticed
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def channel
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
@channel ||= begin
|
|
20
|
+
value = options[:channel]
|
|
21
|
+
case value
|
|
22
|
+
when String
|
|
23
|
+
value.constantize
|
|
24
|
+
when Symbol
|
|
25
|
+
notification.send(value)
|
|
26
|
+
when Class
|
|
27
|
+
value
|
|
28
|
+
else
|
|
29
|
+
Noticed::NotificationChannel
|
|
30
|
+
end
|
|
23
31
|
end
|
|
24
32
|
end
|
|
25
33
|
end
|
|
@@ -4,17 +4,44 @@ module Noticed
|
|
|
4
4
|
extend ActiveModel::Callbacks
|
|
5
5
|
define_model_callbacks :deliver
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
class_attribute :option_names, instance_writer: false, default: []
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
attr_reader :notification, :options, :params, :recipient, :record
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
# Copy option names from parent
|
|
13
|
+
def inherited(base) #:nodoc:
|
|
14
|
+
base.option_names = option_names.dup
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def options(*names)
|
|
19
|
+
option_names.concat Array.wrap(names)
|
|
20
|
+
end
|
|
21
|
+
alias_method :option, :options
|
|
22
|
+
|
|
23
|
+
def validate!(delivery_method_options)
|
|
24
|
+
option_names.each do |option_name|
|
|
25
|
+
unless delivery_method_options.key? option_name
|
|
26
|
+
raise ValidationError, "option `#{option_name}` must be set for #{name}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def perform(args)
|
|
33
|
+
@notification = args[:notification_class].constantize.new(args[:params])
|
|
34
|
+
@options = args[:options]
|
|
35
|
+
@params = args[:params]
|
|
36
|
+
@recipient = args[:recipient]
|
|
37
|
+
@record = args[:record]
|
|
14
38
|
|
|
15
39
|
# Make notification aware of database record and recipient during delivery
|
|
16
|
-
@notification.record = record
|
|
17
|
-
@notification.recipient = recipient
|
|
40
|
+
@notification.record = args[:record]
|
|
41
|
+
@notification.recipient = args[:recipient]
|
|
42
|
+
|
|
43
|
+
return if (condition = @options[:if]) && !@notification.send(condition)
|
|
44
|
+
return if (condition = @options[:unless]) && @notification.send(condition)
|
|
18
45
|
|
|
19
46
|
run_callbacks :deliver do
|
|
20
47
|
deliver
|
|
@@ -24,6 +51,36 @@ module Noticed
|
|
|
24
51
|
def deliver
|
|
25
52
|
raise NotImplementedError, "Delivery methods must implement a deliver method"
|
|
26
53
|
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
# Helper method for making POST requests from delivery methods
|
|
58
|
+
#
|
|
59
|
+
# Usage:
|
|
60
|
+
# post("http://example.com", basic_auth: {user:, pass:}, json: {}, form: {})
|
|
61
|
+
#
|
|
62
|
+
def post(url, args = {})
|
|
63
|
+
basic_auth = args.delete(:basic_auth)
|
|
64
|
+
|
|
65
|
+
request = if basic_auth
|
|
66
|
+
HTTP.basic_auth(user: basic_auth[:user], pass: basic_auth[:pass])
|
|
67
|
+
else
|
|
68
|
+
HTTP
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
response = request.post(url, args)
|
|
72
|
+
|
|
73
|
+
if options[:debug]
|
|
74
|
+
Rails.logger.debug("POST #{url}")
|
|
75
|
+
Rails.logger.debug("Response: #{response.code}: #{response}")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if !options[:ignore_failure] && !response.status.success?
|
|
79
|
+
raise ResponseUnsuccessful.new(response)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
response
|
|
83
|
+
end
|
|
27
84
|
end
|
|
28
85
|
end
|
|
29
86
|
end
|
|
@@ -6,6 +6,13 @@ module Noticed
|
|
|
6
6
|
recipient.send(association_name).create!(attributes)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
def self.validate!(options)
|
|
10
|
+
super
|
|
11
|
+
|
|
12
|
+
# Must be executed right away so the other deliveries can access the db record
|
|
13
|
+
raise ArgumentError, "database delivery cannot be delayed" if options.key?(:delay)
|
|
14
|
+
end
|
|
15
|
+
|
|
9
16
|
private
|
|
10
17
|
|
|
11
18
|
def association_name
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
module Noticed
|
|
2
2
|
module DeliveryMethods
|
|
3
3
|
class Email < Base
|
|
4
|
+
option :mailer
|
|
5
|
+
|
|
4
6
|
def deliver
|
|
5
|
-
mailer.with(format).send(method.to_sym).
|
|
7
|
+
mailer.with(format).send(method.to_sym).deliver_now
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
private
|
|
@@ -16,14 +18,12 @@ module Noticed
|
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
def format
|
|
19
|
-
if (method = options[:format])
|
|
21
|
+
params = if (method = options[:format])
|
|
20
22
|
notification.send(method)
|
|
21
23
|
else
|
|
22
|
-
notification.params
|
|
23
|
-
recipient: recipient,
|
|
24
|
-
record: record
|
|
25
|
-
)
|
|
24
|
+
notification.params
|
|
26
25
|
end
|
|
26
|
+
params.merge(recipient: recipient, record: record)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Noticed
|
|
2
|
+
module DeliveryMethods
|
|
3
|
+
class MicrosoftTeams < Base
|
|
4
|
+
def deliver
|
|
5
|
+
post(url, json: format)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def format
|
|
11
|
+
if (method = options[:format])
|
|
12
|
+
notification.send(method)
|
|
13
|
+
else
|
|
14
|
+
{
|
|
15
|
+
title: notification.params[:title],
|
|
16
|
+
text: notification.params[:text],
|
|
17
|
+
sections: notification.params[:sections],
|
|
18
|
+
potentialAction: notification.params[:notification_action]
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def url
|
|
24
|
+
if (method = options[:url])
|
|
25
|
+
notification.send(method)
|
|
26
|
+
else
|
|
27
|
+
Rails.application.credentials.microsoft_teams[:notification_url]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -2,7 +2,7 @@ module Noticed
|
|
|
2
2
|
module DeliveryMethods
|
|
3
3
|
class Slack < Base
|
|
4
4
|
def deliver
|
|
5
|
-
|
|
5
|
+
post(url, json: format)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
private
|
|
@@ -11,7 +11,7 @@ module Noticed
|
|
|
11
11
|
if (method = options[:format])
|
|
12
12
|
notification.send(method)
|
|
13
13
|
else
|
|
14
|
-
params
|
|
14
|
+
notification.params
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -2,7 +2,13 @@ module Noticed
|
|
|
2
2
|
module DeliveryMethods
|
|
3
3
|
class Vonage < Base
|
|
4
4
|
def deliver
|
|
5
|
-
|
|
5
|
+
response = post("https://rest.nexmo.com/sms/json", json: format)
|
|
6
|
+
status = response.parse.dig("messages", 0, "status")
|
|
7
|
+
if !options[:ignore_failure] && status != "0"
|
|
8
|
+
raise ResponseUnsuccessful.new(response)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
response
|
|
6
12
|
end
|
|
7
13
|
|
|
8
14
|
private
|
data/lib/noticed/engine.rb
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Noticed
|
|
2
|
+
module HasNotifications
|
|
3
|
+
# Defines a method for the association and a before_destory callback to remove notifications
|
|
4
|
+
# where this record is a param
|
|
5
|
+
#
|
|
6
|
+
# class User < ApplicationRecord
|
|
7
|
+
# has_noticed_notifications
|
|
8
|
+
# has_noticed_notifications param_name: :owner, destroy: false, model: "Notification"
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
# @user.notifications_as_user
|
|
12
|
+
# @user.notifications_as_owner
|
|
13
|
+
|
|
14
|
+
extend ActiveSupport::Concern
|
|
15
|
+
|
|
16
|
+
class_methods do
|
|
17
|
+
def has_noticed_notifications(param_name: model_name.singular, **options)
|
|
18
|
+
model = options.fetch(:model_name, "Notification").constantize
|
|
19
|
+
|
|
20
|
+
define_method "notifications_as_#{param_name}" do
|
|
21
|
+
model.where(params: {param_name.to_sym => self})
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
if options.fetch(:destroy, true)
|
|
25
|
+
before_destroy do
|
|
26
|
+
send("notifications_as_#{param_name}").destroy_all
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/noticed/model.rb
CHANGED
|
@@ -5,32 +5,51 @@ module Noticed
|
|
|
5
5
|
included do
|
|
6
6
|
self.inheritance_column = nil
|
|
7
7
|
|
|
8
|
-
serialize :params,
|
|
8
|
+
serialize :params, noticed_coder
|
|
9
9
|
|
|
10
10
|
belongs_to :recipient, polymorphic: true
|
|
11
11
|
|
|
12
12
|
scope :newest_first, -> { order(created_at: :desc) }
|
|
13
|
+
scope :unread, -> { where(read_at: nil) }
|
|
14
|
+
scope :read, -> { where.not(read_at: nil) }
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
class_methods do
|
|
16
18
|
def mark_as_read!
|
|
17
19
|
update_all(read_at: Time.current, updated_at: Time.current)
|
|
18
20
|
end
|
|
21
|
+
|
|
22
|
+
def mark_as_unread!
|
|
23
|
+
update_all(read_at: nil, updated_at: Time.current)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def noticed_coder
|
|
27
|
+
case attribute_types["params"].type
|
|
28
|
+
when :json, :jsonb
|
|
29
|
+
Noticed::Coder
|
|
30
|
+
else
|
|
31
|
+
Noticed::TextCoder
|
|
32
|
+
end
|
|
33
|
+
end
|
|
19
34
|
end
|
|
20
35
|
|
|
21
36
|
# Rehydrate the database notification into the Notification object for rendering
|
|
22
37
|
def to_notification
|
|
23
38
|
@_notification ||= begin
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
instance = type.constantize.with(params)
|
|
40
|
+
instance.record = self
|
|
41
|
+
instance
|
|
42
|
+
end
|
|
28
43
|
end
|
|
29
44
|
|
|
30
45
|
def mark_as_read!
|
|
31
46
|
update(read_at: Time.current)
|
|
32
47
|
end
|
|
33
48
|
|
|
49
|
+
def mark_as_unread!
|
|
50
|
+
update(read_at: nil)
|
|
51
|
+
end
|
|
52
|
+
|
|
34
53
|
def unread?
|
|
35
54
|
!read?
|
|
36
55
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Noticed
|
|
2
|
+
class TextCoder
|
|
3
|
+
def self.load(data)
|
|
4
|
+
return if data.nil?
|
|
5
|
+
|
|
6
|
+
# Text columns need JSON parsing
|
|
7
|
+
data = JSON.parse(data)
|
|
8
|
+
ActiveJob::Arguments.send(:deserialize_argument, data)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.dump(data)
|
|
12
|
+
return if data.nil?
|
|
13
|
+
ActiveJob::Arguments.send(:serialize_argument, data).to_json
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/noticed/translation.rb
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
module
|
|
2
|
-
|
|
1
|
+
module Noticed
|
|
2
|
+
module Translation
|
|
3
|
+
extend ActiveSupport::Concern
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
# Returns the +i18n_scope+ for the class. Overwrite if you want custom lookup.
|
|
6
|
+
def i18n_scope
|
|
7
|
+
:notifications
|
|
8
|
+
end
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
def translate(key, **options)
|
|
11
|
+
I18n.translate(scope_translation_key(key), **options)
|
|
12
|
+
end
|
|
13
|
+
alias_method :t, :translate
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
def scope_translation_key(key)
|
|
16
|
+
if key.to_s.start_with?(".")
|
|
17
|
+
"#{i18n_scope}.#{self.class.name.underscore}#{key}"
|
|
18
|
+
else
|
|
19
|
+
key
|
|
20
|
+
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
end
|
data/lib/noticed/version.rb
CHANGED
data/lib/noticed.rb
CHANGED
|
@@ -5,8 +5,11 @@ require "noticed/engine"
|
|
|
5
5
|
module Noticed
|
|
6
6
|
autoload :Base, "noticed/base"
|
|
7
7
|
autoload :Coder, "noticed/coder"
|
|
8
|
+
autoload :HasNotifications, "noticed/has_notifications"
|
|
8
9
|
autoload :Model, "noticed/model"
|
|
10
|
+
autoload :TextCoder, "noticed/text_coder"
|
|
9
11
|
autoload :Translation, "noticed/translation"
|
|
12
|
+
autoload :NotificationChannel, "noticed/notification_channel"
|
|
10
13
|
|
|
11
14
|
module DeliveryMethods
|
|
12
15
|
autoload :Base, "noticed/delivery_methods/base"
|
|
@@ -14,6 +17,7 @@ module Noticed
|
|
|
14
17
|
autoload :Database, "noticed/delivery_methods/database"
|
|
15
18
|
autoload :Email, "noticed/delivery_methods/email"
|
|
16
19
|
autoload :Slack, "noticed/delivery_methods/slack"
|
|
20
|
+
autoload :MicrosoftTeams, "noticed/delivery_methods/microsoft_teams"
|
|
17
21
|
autoload :Test, "noticed/delivery_methods/test"
|
|
18
22
|
autoload :Twilio, "noticed/delivery_methods/twilio"
|
|
19
23
|
autoload :Vonage, "noticed/delivery_methods/vonage"
|
|
@@ -33,4 +37,12 @@ module Noticed
|
|
|
33
37
|
|
|
34
38
|
class ValidationError < StandardError
|
|
35
39
|
end
|
|
40
|
+
|
|
41
|
+
class ResponseUnsuccessful < StandardError
|
|
42
|
+
attr_reader :response
|
|
43
|
+
|
|
44
|
+
def initialize(response)
|
|
45
|
+
@response = response
|
|
46
|
+
end
|
|
47
|
+
end
|
|
36
48
|
end
|
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: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Oliver
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-03-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -67,7 +67,35 @@ dependencies:
|
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
70
|
+
name: webmock
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: mysql2
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: sqlite3
|
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
|
72
100
|
requirements:
|
|
73
101
|
- - ">="
|
|
@@ -91,10 +119,11 @@ files:
|
|
|
91
119
|
- MIT-LICENSE
|
|
92
120
|
- README.md
|
|
93
121
|
- Rakefile
|
|
94
|
-
-
|
|
122
|
+
- lib/generators/noticed/delivery_method_generator.rb
|
|
95
123
|
- lib/generators/noticed/model_generator.rb
|
|
96
124
|
- lib/generators/noticed/notification_generator.rb
|
|
97
125
|
- lib/generators/noticed/templates/README
|
|
126
|
+
- lib/generators/noticed/templates/delivery_method.rb.tt
|
|
98
127
|
- lib/generators/noticed/templates/notification.rb.tt
|
|
99
128
|
- lib/noticed.rb
|
|
100
129
|
- lib/noticed/base.rb
|
|
@@ -103,12 +132,16 @@ files:
|
|
|
103
132
|
- lib/noticed/delivery_methods/base.rb
|
|
104
133
|
- lib/noticed/delivery_methods/database.rb
|
|
105
134
|
- lib/noticed/delivery_methods/email.rb
|
|
135
|
+
- lib/noticed/delivery_methods/microsoft_teams.rb
|
|
106
136
|
- lib/noticed/delivery_methods/slack.rb
|
|
107
137
|
- lib/noticed/delivery_methods/test.rb
|
|
108
138
|
- lib/noticed/delivery_methods/twilio.rb
|
|
109
139
|
- lib/noticed/delivery_methods/vonage.rb
|
|
110
140
|
- lib/noticed/engine.rb
|
|
141
|
+
- lib/noticed/has_notifications.rb
|
|
111
142
|
- lib/noticed/model.rb
|
|
143
|
+
- lib/noticed/notification_channel.rb
|
|
144
|
+
- lib/noticed/text_coder.rb
|
|
112
145
|
- lib/noticed/translation.rb
|
|
113
146
|
- lib/noticed/version.rb
|
|
114
147
|
- lib/tasks/noticed_tasks.rake
|
|
@@ -116,7 +149,7 @@ homepage: https://github.com/excid3/noticed
|
|
|
116
149
|
licenses:
|
|
117
150
|
- MIT
|
|
118
151
|
metadata: {}
|
|
119
|
-
post_install_message:
|
|
152
|
+
post_install_message:
|
|
120
153
|
rdoc_options: []
|
|
121
154
|
require_paths:
|
|
122
155
|
- lib
|
|
@@ -131,8 +164,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
131
164
|
- !ruby/object:Gem::Version
|
|
132
165
|
version: '0'
|
|
133
166
|
requirements: []
|
|
134
|
-
rubygems_version: 3.
|
|
135
|
-
signing_key:
|
|
167
|
+
rubygems_version: 3.2.3
|
|
168
|
+
signing_key:
|
|
136
169
|
specification_version: 4
|
|
137
170
|
summary: Notifications for Ruby on Rails applications
|
|
138
171
|
test_files: []
|
|
File without changes
|