noticed 1.2.15 → 1.2.20

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69785568f3cfb7b464a3dfbb7ce8bd0813acbdcd3f96059122c2a9b24ade12d2
4
- data.tar.gz: 3c9464383b48f2df3605b7aa1062519e867f2ebfae7dde21ccc25ac69afab258
3
+ metadata.gz: e5b998072ed72c9844842d8610a9ffcea75cf16f958296aa3d53e1a3c050b6db
4
+ data.tar.gz: 589f43985b3dc7740977730d10917d0b111706fe56c4daafedbacc08e7f2ce84
5
5
  SHA512:
6
- metadata.gz: 539e60472bad43dd44239ecbcbd79ad9dff86cb8105d7923657e62ffa6b1fe9a3ef6ced17b823597e907645ec5837985aaee7cc7da8b2f89f7d85fa1b6b881bd
7
- data.tar.gz: 34bb2249fafab5002d569ddd267a3944e43e03b51a793ed162c3166900699b658efdb8ace15a3a6dca29000aa68787046732d2d1df88b31468fc096ffd18641f
6
+ metadata.gz: 9f4a336ed688008a5abc3f91099a5ecc4128361beffd216e0e2e0bc0a1670286e607577d2f4ce13f1e36c2fb2fff3d93fbab9a10914d0321a2d1e0c2449ea715
7
+ data.tar.gz: b4a67b79dcf34892dcd11b56ad83e2c393a2da49c3eb38e3e911411164b4150ec27a836e53d1d7875ea40141276a398878e8c23304c326287299b26bafebacba
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
 
@@ -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.
@@ -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 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
+
249
294
  ### Twilio SMS
250
295
 
251
296
  Sends an SMS notification via Twilio.
@@ -342,19 +387,24 @@ Delivery methods have access to the following methods and attributes:
342
387
 
343
388
  #### Validating options passed to Custom Delivery methods
344
389
 
345
- You can validate the options passed to the custom delivery method and raise validation errors. This is helpful for debugging to make sure valid and required options were passed in.
390
+ The presence of the delivery method options is automatically validated if using the `option(s)` method.
346
391
 
347
- To do this, simply override the `self.validate!(options)` method from the `Noticed::DeliveryMethods::Base` class in your Custom Delivery method.
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.
348
393
 
349
394
  ```ruby
350
395
  class DeliveryMethods::Discord < Noticed::DeliveryMethods::Base
396
+ option :username # Requires the username option to be passed
397
+
351
398
  def deliver
352
399
  # Logic for sending a Discord notification
353
400
  end
354
401
 
355
- def self.validate!(options)
356
- unless options.key?(:sent_by)
357
- raise Noticed::ValidationError, 'the `sent_by` option is missing'
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'
358
408
  end
359
409
  end
360
410
  end
@@ -370,7 +420,7 @@ To fix the error, the argument has to be passed correctly. For example:
370
420
 
371
421
  ```ruby
372
422
  class CommentNotification < Noticed::Base
373
- deliver_by :discord, class: 'DeliveryMethods::Discord', sent_by: User.admin.first
423
+ deliver_by :discord, class: 'DeliveryMethods::Discord', username: User.admin.username
374
424
  end
375
425
  ```
376
426
 
@@ -394,7 +444,7 @@ Rails 6.1+ can serialize Class and Module objects as arguments to ActiveJob. The
394
444
  deliver_by DeliveryMethods::Discord
395
445
  ```
396
446
 
397
- For Rails 6.0 and earlier, you must pass strings of the class names in the `deliver_by` options.
447
+ For Rails 6.0, you must pass strings of the class names in the `deliver_by` options.
398
448
 
399
449
  ```ruby
400
450
  deliver_by :discord, class: "DeliveryMethods::Discord"
@@ -414,10 +464,19 @@ Sorting notifications by newest first:
414
464
  user.notifications.newest_first
415
465
  ```
416
466
 
417
- Marking all notifications as read:
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:
418
476
 
419
477
  ```ruby
420
478
  user.notifications.mark_as_read!
479
+ user.notifications.mark_as_unread!
421
480
  ```
422
481
 
423
482
  #### Instance methods
@@ -428,10 +487,11 @@ Convert back into a Noticed notification object:
428
487
  @notification.to_notification
429
488
  ```
430
489
 
431
- Mark notification as read:
490
+ Mark notification as read / unread:
432
491
 
433
492
  ```ruby
434
493
  @notification.mark_as_read!
494
+ @notification.mark_as_unread!
435
495
  ```
436
496
 
437
497
  Check if read / unread:
@@ -471,7 +531,7 @@ class Post < ApplicationRecord
471
531
  end
472
532
  ```
473
533
 
474
- ##### Polymorphic Assocation
534
+ ##### Polymorphic Association
475
535
 
476
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.
477
537
 
@@ -15,7 +15,7 @@ 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", params_column, "read_at:datetime", *attributes
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
@@ -43,7 +43,7 @@ module Noticed
43
43
 
44
44
  def params_column
45
45
  case ActiveRecord::Base.configurations.configs_for(spec_name: "primary").config["adapter"]
46
- when "mysql"
46
+ when "mysql2"
47
47
  "params:json"
48
48
  when "postgresql"
49
49
  "params:jsonb"
@@ -16,6 +16,7 @@ module Noticed
16
16
  autoload :Database, "noticed/delivery_methods/database"
17
17
  autoload :Email, "noticed/delivery_methods/email"
18
18
  autoload :Slack, "noticed/delivery_methods/slack"
19
+ autoload :MicrosoftTeams, "noticed/delivery_methods/microsoft_teams"
19
20
  autoload :Test, "noticed/delivery_methods/test"
20
21
  autoload :Twilio, "noticed/delivery_methods/twilio"
21
22
  autoload :Vonage, "noticed/delivery_methods/vonage"
@@ -32,7 +32,7 @@ module Noticed
32
32
  def params(*names)
33
33
  param_names.concat Array.wrap(names)
34
34
  end
35
- alias param params
35
+ alias_method :param, :params
36
36
  end
37
37
 
38
38
  def initialize(params = {})
@@ -85,9 +85,6 @@ module Noticed
85
85
 
86
86
  # Actually runs an individual delivery
87
87
  def run_delivery_method(delivery_method, recipient:, enqueue:)
88
- return if (delivery_method_name = delivery_method.dig(:options, :if)) && !send(delivery_method_name)
89
- return if (delivery_method_name = delivery_method.dig(:options, :unless)) && send(delivery_method_name)
90
-
91
88
  args = {
92
89
  notification_class: self.class.name,
93
90
  options: delivery_method[:options],
@@ -98,7 +95,15 @@ module Noticed
98
95
 
99
96
  run_callbacks delivery_method[:name] do
100
97
  method = delivery_method_for(delivery_method[:name], delivery_method[:options])
101
- enqueue ? method.perform_later(args) : method.perform_now(args)
98
+
99
+ # Always perfrom later if a delay is present
100
+ if (delay = delivery_method.dig(:options, :delay))
101
+ method.set(wait: delay).perform_later(args)
102
+ elsif enqueue
103
+ method.perform_later(args)
104
+ else
105
+ method.perform_now(args)
106
+ end
102
107
  end
103
108
  end
104
109
 
@@ -106,7 +111,7 @@ module Noticed
106
111
  if options[:class]
107
112
  options[:class].constantize
108
113
  else
109
- "Noticed::DeliveryMethods::#{name.to_s.classify}".constantize
114
+ "Noticed::DeliveryMethods::#{name.to_s.camelize}".constantize
110
115
  end
111
116
  end
112
117
 
@@ -17,18 +17,18 @@ module Noticed
17
17
 
18
18
  def channel
19
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
31
- end
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
31
+ end
32
32
  end
33
33
  end
34
34
  end
@@ -4,8 +4,31 @@ module Noticed
4
4
  extend ActiveModel::Callbacks
5
5
  define_model_callbacks :deliver
6
6
 
7
+ class_attribute :option_names, instance_writer: false, default: []
8
+
7
9
  attr_reader :notification, :options, :params, :recipient, :record
8
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
+
9
32
  def perform(args)
10
33
  @notification = args[:notification_class].constantize.new(args[:params])
11
34
  @options = args[:options]
@@ -17,6 +40,9 @@ module Noticed
17
40
  @notification.record = args[:record]
18
41
  @notification.recipient = args[:recipient]
19
42
 
43
+ return if (condition = @options[:if]) && !@notification.send(condition)
44
+ return if (condition = @options[:unless]) && @notification.send(condition)
45
+
20
46
  run_callbacks :deliver do
21
47
  deliver
22
48
  end
@@ -26,11 +52,6 @@ module Noticed
26
52
  raise NotImplementedError, "Delivery methods must implement a deliver method"
27
53
  end
28
54
 
29
- def self.validate!(options)
30
- # Override this method in your custom DeliveryMethod class to validate the options
31
- # and raise error, if invalid.
32
- end
33
-
34
55
  private
35
56
 
36
57
  # Helper method for making POST requests from delivery methods
@@ -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,14 +1,10 @@
1
1
  module Noticed
2
2
  module DeliveryMethods
3
3
  class Email < Base
4
- def deliver
5
- mailer.with(format).send(method.to_sym).deliver_later
6
- end
4
+ option :mailer
7
5
 
8
- def self.validate!(options)
9
- unless options.key?(:mailer)
10
- raise ValidationError, "email delivery method requires a 'mailer' to be specified"
11
- end
6
+ def deliver
7
+ mailer.with(format).send(method.to_sym).deliver_now
12
8
  end
13
9
 
14
10
  private
@@ -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
@@ -7,6 +7,8 @@ module Noticed
7
7
  if !options[:ignore_failure] && status != "0"
8
8
  raise ResponseUnsuccessful.new(response)
9
9
  end
10
+
11
+ response
10
12
  end
11
13
 
12
14
  private
@@ -14,11 +14,15 @@ module Noticed
14
14
  scope :read, -> { where.not(read_at: nil) }
15
15
  end
16
16
 
17
- module ClassMethods
17
+ class_methods do
18
18
  def mark_as_read!
19
19
  update_all(read_at: Time.current, updated_at: Time.current)
20
20
  end
21
21
 
22
+ def mark_as_unread!
23
+ update_all(read_at: nil, updated_at: Time.current)
24
+ end
25
+
22
26
  def noticed_coder
23
27
  case attribute_types["params"].type
24
28
  when :json, :jsonb
@@ -32,16 +36,20 @@ module Noticed
32
36
  # Rehydrate the database notification into the Notification object for rendering
33
37
  def to_notification
34
38
  @_notification ||= begin
35
- instance = type.constantize.with(params)
36
- instance.record = self
37
- instance
38
- end
39
+ instance = type.constantize.with(params)
40
+ instance.record = self
41
+ instance
42
+ end
39
43
  end
40
44
 
41
45
  def mark_as_read!
42
46
  update(read_at: Time.current)
43
47
  end
44
48
 
49
+ def mark_as_unread!
50
+ update(read_at: nil)
51
+ end
52
+
45
53
  def unread?
46
54
  !read?
47
55
  end
@@ -10,7 +10,7 @@ module Noticed
10
10
  def translate(key, **options)
11
11
  I18n.translate(scope_translation_key(key), **options)
12
12
  end
13
- alias t translate
13
+ alias_method :t, :translate
14
14
 
15
15
  def scope_translation_key(key)
16
16
  if key.to_s.start_with?(".")
@@ -1,3 +1,3 @@
1
1
  module Noticed
2
- VERSION = "1.2.15"
2
+ VERSION = "1.2.20"
3
3
  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.2.15
4
+ version: 1.2.20
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: 2020-09-02 00:00:00.000000000 Z
11
+ date: 2020-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -67,7 +67,21 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: mocha
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
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
@@ -104,6 +118,7 @@ files:
104
118
  - lib/noticed/delivery_methods/base.rb
105
119
  - lib/noticed/delivery_methods/database.rb
106
120
  - lib/noticed/delivery_methods/email.rb
121
+ - lib/noticed/delivery_methods/microsoft_teams.rb
107
122
  - lib/noticed/delivery_methods/slack.rb
108
123
  - lib/noticed/delivery_methods/test.rb
109
124
  - lib/noticed/delivery_methods/twilio.rb
@@ -119,7 +134,7 @@ homepage: https://github.com/excid3/noticed
119
134
  licenses:
120
135
  - MIT
121
136
  metadata: {}
122
- post_install_message:
137
+ post_install_message:
123
138
  rdoc_options: []
124
139
  require_paths:
125
140
  - lib
@@ -134,8 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
149
  - !ruby/object:Gem::Version
135
150
  version: '0'
136
151
  requirements: []
137
- rubygems_version: 3.1.2
138
- signing_key:
152
+ rubygems_version: 3.1.4
153
+ signing_key:
139
154
  specification_version: 4
140
155
  summary: Notifications for Ruby on Rails applications
141
156
  test_files: []