noticed 2.0.0 → 3.0.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +624 -185
  3. data/app/jobs/noticed/event_job.rb +5 -7
  4. data/app/models/concerns/noticed/deliverable.rb +60 -18
  5. data/app/models/concerns/noticed/notification_methods.rb +1 -1
  6. data/app/models/concerns/noticed/readable.rb +32 -8
  7. data/app/models/noticed/deliverable/deliver_by.rb +28 -7
  8. data/app/models/noticed/ephemeral.rb +63 -0
  9. data/app/models/noticed/event.rb +13 -0
  10. data/app/models/noticed/notification.rb +3 -3
  11. data/db/migrate/20231215190233_create_noticed_tables.rb +16 -5
  12. data/db/migrate/20240129184740_add_notifications_count_to_noticed_event.rb +5 -0
  13. data/lib/generators/noticed/delivery_method_generator.rb +9 -1
  14. data/lib/generators/noticed/notifier_generator.rb +14 -1
  15. data/lib/generators/noticed/templates/application_bulk_delivery_method.rb.tt +2 -0
  16. data/lib/generators/noticed/templates/application_delivery_method.rb.tt +2 -0
  17. data/lib/generators/noticed/templates/application_notifier.rb.tt +2 -0
  18. data/lib/generators/noticed/templates/bulk_delivery_method.rb.tt +14 -0
  19. data/lib/generators/noticed/templates/delivery_method.rb.tt +10 -8
  20. data/lib/generators/noticed/templates/notifier.rb.tt +8 -2
  21. data/lib/noticed/api_client.rb +3 -1
  22. data/lib/noticed/bulk_delivery_method.rb +19 -7
  23. data/lib/noticed/bulk_delivery_methods/bluesky.rb +51 -0
  24. data/lib/noticed/bulk_delivery_methods/discord.rb +2 -0
  25. data/lib/noticed/bulk_delivery_methods/slack.rb +25 -1
  26. data/lib/noticed/bulk_delivery_methods/test.rb +13 -0
  27. data/lib/noticed/bulk_delivery_methods/webhook.rb +4 -1
  28. data/lib/noticed/coder.rb +5 -1
  29. data/lib/noticed/delivery_method.rb +21 -8
  30. data/lib/noticed/delivery_methods/action_cable.rb +11 -5
  31. data/lib/noticed/delivery_methods/action_push_native.rb +24 -0
  32. data/lib/noticed/delivery_methods/discord.rb +2 -0
  33. data/lib/noticed/delivery_methods/email.rb +13 -5
  34. data/lib/noticed/delivery_methods/fcm.rb +19 -2
  35. data/lib/noticed/delivery_methods/ios.rb +15 -4
  36. data/lib/noticed/delivery_methods/microsoft_teams.rb +2 -0
  37. data/lib/noticed/delivery_methods/slack.rb +25 -1
  38. data/lib/noticed/delivery_methods/test.rb +2 -0
  39. data/lib/noticed/delivery_methods/twilio_messaging.rb +9 -1
  40. data/lib/noticed/delivery_methods/vonage_sms.rb +2 -0
  41. data/lib/noticed/delivery_methods/webhook.rb +4 -1
  42. data/lib/noticed/engine.rb +10 -0
  43. data/lib/noticed/has_notifications.rb +49 -0
  44. data/lib/noticed/notification_channel.rb +19 -0
  45. data/lib/noticed/version.rb +1 -1
  46. data/lib/noticed.rb +15 -27
  47. metadata +14 -6
@@ -1,17 +1,15 @@
1
1
  module Noticed
2
- class EventJob < ApplicationJob
3
- queue_as :default
4
-
2
+ class EventJob < Noticed.parent_class.constantize
5
3
  def perform(event)
6
4
  # Enqueue bulk deliveries
7
- event.bulk_delivery_methods.each do |_, deliver_by|
8
- deliver_by.perform_later(event)
5
+ event.bulk_delivery_methods.each_value do |deliver_by|
6
+ deliver_by.perform_later(event) if deliver_by.perform?(event)
9
7
  end
10
8
 
11
9
  # Enqueue individual deliveries
12
10
  event.notifications.each do |notification|
13
- event.delivery_methods.each do |_, deliver_by|
14
- deliver_by.perform_later(notification)
11
+ event.delivery_methods.each_value do |deliver_by|
12
+ deliver_by.perform_later(notification) if deliver_by.perform?(notification)
15
13
  end
16
14
  end
17
15
  end
@@ -6,14 +6,7 @@ module Noticed
6
6
  class_attribute :bulk_delivery_methods, instance_writer: false, default: {}
7
7
  class_attribute :delivery_methods, instance_writer: false, default: {}
8
8
  class_attribute :required_param_names, instance_writer: false, default: []
9
-
10
- attribute :params, default: {}
11
-
12
- if Rails.gem_version >= Gem::Version.new("7.1.0.alpha")
13
- serialize :params, coder: Coder
14
- else
15
- serialize :params, Coder
16
- end
9
+ class_attribute :_recipients, instance_writer: false
17
10
  end
18
11
 
19
12
  class_methods do
@@ -35,24 +28,54 @@ module Noticed
35
28
  def deliver_by(name, options = {})
36
29
  raise NameError, "#{name} has already been used for this Notifier." if delivery_methods.has_key?(name)
37
30
 
31
+ if name == :database
32
+ Noticed.deprecator.warn <<-WARNING.squish
33
+ The :database delivery method has been deprecated and does nothing. Notifiers automatically save to the database now.
34
+ WARNING
35
+ return
36
+ end
37
+
38
38
  config = ActiveSupport::OrderedOptions.new.merge(options)
39
39
  yield config if block_given?
40
40
  delivery_methods[name] = DeliverBy.new(name, config)
41
41
  end
42
42
 
43
+ def recipients(option = nil, &block)
44
+ self._recipients = block || option
45
+ end
46
+
43
47
  def required_params(*names)
44
48
  required_param_names.concat names
45
49
  end
46
50
  alias_method :required_param, :required_params
47
51
 
52
+ def params(*names)
53
+ Noticed.deprecator.warn <<-WARNING.squish
54
+ `params` is deprecated and has been renamed to `required_params`
55
+ WARNING
56
+ required_params(*names)
57
+ end
58
+
59
+ def param(*names)
60
+ Noticed.deprecator.warn <<-WARNING.squish
61
+ `param :name` is deprecated and has been renamed to `required_param :name`
62
+ WARNING
63
+ required_params(*names)
64
+ end
65
+
48
66
  def with(params)
49
- record = params.delete(:record)
50
- new(params: params, record: record)
67
+ if self < Ephemeral
68
+ new(params: params)
69
+ else
70
+ record = params.delete(:record)
71
+ new(params: params, record: record)
72
+ end
51
73
  end
52
74
 
53
- def deliver(recipients = nil, options = {})
54
- new.deliver(recipients, options)
75
+ def deliver(recipients = nil, **options)
76
+ new.deliver(recipients, **options)
55
77
  end
78
+ alias_method :deliver_later, :deliver
56
79
  end
57
80
 
58
81
  # CommentNotifier.deliver(User.all)
@@ -60,16 +83,19 @@ module Noticed
60
83
  # CommentNotifier.deliver(User.all, queue: :low_priority)
61
84
  # CommentNotifier.deliver(User.all, wait: 5.minutes)
62
85
  # CommentNotifier.deliver(User.all, wait_until: 1.hour.from_now)
63
- def deliver(recipients = nil, options = {})
86
+ def deliver(recipients = nil, enqueue_job: true, **options)
87
+ recipients ||= evaluate_recipients
88
+
64
89
  validate!
65
90
 
66
91
  transaction do
67
- save!
68
-
69
92
  recipients_attributes = Array.wrap(recipients).map do |recipient|
70
93
  recipient_attributes_for(recipient)
71
94
  end
72
95
 
96
+ self.notifications_count = recipients_attributes.size
97
+ save!
98
+
73
99
  if Rails.gem_version >= Gem::Version.new("7.0.0.alpha1")
74
100
  notifications.insert_all!(recipients_attributes, record_timestamps: true) if recipients_attributes.any?
75
101
  else
@@ -83,15 +109,26 @@ module Noticed
83
109
  end
84
110
 
85
111
  # Enqueue delivery job
86
- EventJob.set(options).perform_later(self)
112
+ EventJob.set(options).perform_later(self) if enqueue_job
87
113
 
88
114
  self
89
115
  end
116
+ alias_method :deliver_later, :deliver
117
+
118
+ def evaluate_recipients
119
+ return unless _recipients
120
+
121
+ if _recipients.respond_to?(:call, true)
122
+ instance_exec(&_recipients)
123
+ elsif _recipients.is_a?(Symbol) && respond_to?(_recipients, true)
124
+ send(_recipients)
125
+ end
126
+ end
90
127
 
91
128
  def recipient_attributes_for(recipient)
92
129
  {
93
130
  type: "#{self.class.name}::Notification",
94
- recipient_type: recipient.class.name,
131
+ recipient_type: recipient.class.base_class.name,
95
132
  recipient_id: recipient.id
96
133
  }
97
134
  end
@@ -103,7 +140,7 @@ module Noticed
103
140
 
104
141
  def validate_params!
105
142
  required_param_names.each do |param_name|
106
- raise ValidationError, "Param `#{param_name}` is required for #{self.class.name}." unless params[param_name].present?
143
+ raise ValidationError, "Param `#{param_name}` is required for #{self.class.name}." unless params.has_key?(param_name)
107
144
  end
108
145
  end
109
146
 
@@ -111,5 +148,10 @@ module Noticed
111
148
  bulk_delivery_methods.values.each(&:validate!)
112
149
  delivery_methods.values.each(&:validate!)
113
150
  end
151
+
152
+ # If a GlobalID record in params is no longer found, the params will default with a noticed_error key
153
+ def deserialize_error?
154
+ !!params[:noticed_error]
155
+ end
114
156
  end
115
157
  end
@@ -6,7 +6,7 @@ module Noticed
6
6
  # Generate a Notification class each time a Notifier is defined
7
7
  def inherited(notifier)
8
8
  super
9
- notifier.const_set :Notification, Class.new(Noticed::Notification)
9
+ notifier.const_set :Notification, Class.new(const_defined?(:Notification) ? const_get(:Notification) : Noticed::Notification)
10
10
  end
11
11
 
12
12
  def notification_methods(&block)
@@ -10,20 +10,28 @@ module Noticed
10
10
  end
11
11
 
12
12
  class_methods do
13
- def mark_as_read
14
- update_all(read_at: Time.current)
13
+ def mark_as_read_and_seen(**kwargs)
14
+ update_all(**kwargs.with_defaults(read_at: Time.current, seen_at: Time.current, updated_at: Time.current))
15
15
  end
16
16
 
17
- def mark_as_unread
18
- update_all(read_at: nil)
17
+ def mark_as_unread_and_unseen(**kwargs)
18
+ update_all(**kwargs.with_defaults(read_at: nil, seen_at: nil, updated_at: Time.current))
19
19
  end
20
20
 
21
- def mark_as_seen
22
- update_all(seen_at: Time.current)
21
+ def mark_as_read(**kwargs)
22
+ update_all(**kwargs.with_defaults(read_at: Time.current, updated_at: Time.current))
23
23
  end
24
24
 
25
- def mark_as_unseen
26
- update_all(seen_at: nil)
25
+ def mark_as_unread(**kwargs)
26
+ update_all(**kwargs.with_defaults(read_at: nil, updated_at: Time.current))
27
+ end
28
+
29
+ def mark_as_seen(**kwargs)
30
+ update_all(**kwargs.with_defaults(seen_at: Time.current, updated_at: Time.current))
31
+ end
32
+
33
+ def mark_as_unseen(**kwargs)
34
+ update_all(**kwargs.with_defaults(seen_at: nil, updated_at: Time.current))
27
35
  end
28
36
  end
29
37
 
@@ -31,18 +39,34 @@ module Noticed
31
39
  update(read_at: Time.current)
32
40
  end
33
41
 
42
+ def mark_as_read!
43
+ update!(read_at: Time.current)
44
+ end
45
+
34
46
  def mark_as_unread
35
47
  update(read_at: nil)
36
48
  end
37
49
 
50
+ def mark_as_unread!
51
+ update!(read_at: nil)
52
+ end
53
+
38
54
  def mark_as_seen
39
55
  update(seen_at: Time.current)
40
56
  end
41
57
 
58
+ def mark_as_seen!
59
+ update!(seen_at: Time.current)
60
+ end
61
+
42
62
  def mark_as_unseen
43
63
  update(seen_at: nil)
44
64
  end
45
65
 
66
+ def mark_as_unseen!
67
+ update!(seen_at: nil)
68
+ end
69
+
46
70
  def read?
47
71
  read_at?
48
72
  end
@@ -19,25 +19,46 @@ module Noticed
19
19
  end
20
20
 
21
21
  def perform_later(event_or_notification, options = {})
22
- options[:wait] = evaluate_option(:wait, event_or_notification) if config.has_key?(:wait)
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)
22
+ constant.set(computed_options(options, event_or_notification)).perform_later(name, event_or_notification)
23
+ end
26
24
 
27
- constant.set(options).perform_later(name, event_or_notification)
25
+ def ephemeral_perform_later(notifier, recipient, params, options = {})
26
+ constant.set(computed_options(options, recipient))
27
+ .perform_later(name, "#{notifier}::Notification", recipient: recipient, params: params)
28
28
  end
29
29
 
30
30
  def evaluate_option(name, context)
31
31
  option = config[name]
32
32
 
33
- if option&.respond_to?(:call)
33
+ if option.respond_to?(:call)
34
34
  context.instance_exec(&option)
35
- elsif option.is_a?(Symbol) && context.respond_to?(option)
35
+ elsif option.is_a?(Symbol) && context.respond_to?(option, true)
36
36
  context.send(option)
37
37
  else
38
38
  option
39
39
  end
40
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
41
62
  end
42
63
  end
43
64
  end
@@ -0,0 +1,63 @@
1
+ module Noticed
2
+ class Ephemeral
3
+ include ActiveModel::Model
4
+ include ActiveModel::Attributes
5
+ include Noticed::Deliverable
6
+ include Noticed::Translation
7
+ include Rails.application.routes.url_helpers
8
+
9
+ attribute :record
10
+ attribute :params, default: {}
11
+
12
+ class Notification
13
+ include ActiveModel::Model
14
+ include ActiveModel::Attributes
15
+ include Noticed::Translation
16
+ include Rails.application.routes.url_helpers
17
+
18
+ attribute :recipient
19
+ attribute :event
20
+
21
+ delegate :params, :record, to: :event
22
+
23
+ def self.new_with_params(recipient, params)
24
+ instance = new(recipient: recipient)
25
+ instance.event = module_parent.new(params: params)
26
+ instance
27
+ end
28
+ end
29
+
30
+ # Dynamically define Notification on each Ephemeral Notifier
31
+ def self.inherited(notifier)
32
+ super
33
+ notifier.const_set :Notification, Class.new(Noticed::Ephemeral::Notification)
34
+ end
35
+
36
+ def self.notification_methods(&block)
37
+ const_get(:Notification).class_eval(&block)
38
+ end
39
+
40
+ def deliver(recipients = nil)
41
+ recipients ||= evaluate_recipients
42
+ recipients = Array.wrap(recipients)
43
+
44
+ bulk_delivery_methods.each do |_, deliver_by|
45
+ deliver_by.ephemeral_perform_later(self.class.name, recipients, params)
46
+ end
47
+
48
+ recipients.each do |recipient|
49
+ delivery_methods.each do |_, deliver_by|
50
+ deliver_by.ephemeral_perform_later(self.class.name, recipient, params)
51
+ end
52
+ end
53
+
54
+ self
55
+ end
56
+
57
+ def record
58
+ params[:record]
59
+ end
60
+ end
61
+ end
62
+
63
+ ActiveSupport.run_load_hooks :noticed_ephemeral, Noticed::Ephemeral
@@ -11,5 +11,18 @@ module Noticed
11
11
  accepts_nested_attributes_for :notifications
12
12
 
13
13
  scope :newest_first, -> { order(created_at: :desc) }
14
+
15
+ attribute :params, :json, default: {}
16
+
17
+ # Ephemeral notifiers cannot serialize params since they aren't ActiveRecord backed
18
+ if respond_to? :serialize
19
+ if Rails.gem_version >= Gem::Version.new("7.1.0.alpha")
20
+ serialize :params, coder: Coder
21
+ else
22
+ serialize :params, Coder
23
+ end
24
+ end
14
25
  end
15
26
  end
27
+
28
+ ActiveSupport.run_load_hooks :noticed_event, Noticed::Event
@@ -4,13 +4,13 @@ module Noticed
4
4
  include Readable
5
5
  include Translation
6
6
 
7
- belongs_to :event
7
+ belongs_to :event, counter_cache: true
8
8
  belongs_to :recipient, polymorphic: true
9
9
 
10
10
  scope :newest_first, -> { order(created_at: :desc) }
11
11
 
12
12
  delegate :params, :record, to: :event
13
-
14
- attribute :params, default: {}
15
13
  end
16
14
  end
15
+
16
+ ActiveSupport.run_load_hooks :noticed_notification, Noticed::Notification
@@ -1,8 +1,9 @@
1
1
  class CreateNoticedTables < ActiveRecord::Migration[6.1]
2
2
  def change
3
- create_table :noticed_events do |t|
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
@@ -0,0 +1,5 @@
1
+ class AddNotificationsCountToNoticedEvent < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :noticed_events, :notifications_count, :integer
4
+ end
5
+ end
@@ -11,8 +11,16 @@ module Noticed
11
11
 
12
12
  desc "Generates a class for a custom delivery method with the given NAME."
13
13
 
14
+ class_option :bulk, desc: "Generate as a bulk delivery method", type: :boolean, default: false
15
+
14
16
  def generate_notification
15
- template "delivery_method.rb", "app/notifiers/delivery_methods/#{singular_name}.rb"
17
+ if options[:bulk]
18
+ template "application_bulk_delivery_method.rb", "app/notifiers/application_bulk_delivery_method.rb"
19
+ template "bulk_delivery_method.rb", "app/notifiers/bulk_delivery_methods/#{singular_name}.rb"
20
+ else
21
+ template "application_delivery_method.rb", "app/notifiers/application_delivery_method.rb"
22
+ template "delivery_method.rb", "app/notifiers/delivery_methods/#{singular_name}.rb"
23
+ end
16
24
  end
17
25
  end
18
26
  end
@@ -7,12 +7,25 @@ module Noticed
7
7
  class NotifierGenerator < Rails::Generators::NamedBase
8
8
  include Rails::Generators::ResourceHelpers
9
9
 
10
+ check_class_collision suffix: "Notifier"
11
+
10
12
  source_root File.expand_path("../templates", __FILE__)
11
13
 
12
14
  desc "Generates a notification with the given NAME."
13
15
 
16
+ def generate_abstract_class
17
+ return if File.exist?("app/notifiers/application_notifier.rb")
18
+ template "application_notifier.rb", "app/notifiers/application_notifier.rb"
19
+ end
20
+
14
21
  def generate_notification
15
- template "notifier.rb", "app/notifiers/#{file_path}.rb"
22
+ template "notifier.rb", "app/notifiers/#{file_path}_notifier.rb"
23
+ end
24
+
25
+ private
26
+
27
+ def file_name # :doc:
28
+ @_file_name ||= super.sub(/_notifier\z/i, "")
16
29
  end
17
30
  end
18
31
  end
@@ -0,0 +1,2 @@
1
+ class ApplicationBulkDeliveryMethod < Noticed::BulkDeliveryMethod
2
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationDeliveryMethod < Noticed::DeliveryMethod
2
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationNotifier < Noticed::Event
2
+ end
@@ -0,0 +1,14 @@
1
+ class BulkDeliveryMethods::<%= class_name %> < ApplicationBulkDeliveryMethod
2
+ # To use this delivery method, specify the class option in your notifier.
3
+ #
4
+ # class MyNotifer < ApplicationNotifier
5
+ # bulk_deliver_by :<%= file_path %>, class: "<%= class_name %>"
6
+ # end
7
+
8
+ # Specify required options for the deliver_by config block
9
+ # required_options :foo, :bar
10
+
11
+ def deliver
12
+ # Logic for sending the notification
13
+ end
14
+ end
@@ -1,12 +1,14 @@
1
- class DeliveryMethods::<%= class_name %> < Noticed::DeliveryMethods::Base
1
+ class DeliveryMethods::<%= class_name %> < ApplicationDeliveryMethod
2
+ # To use this delivery method, specify the class option in your notifier.
3
+ #
4
+ # class MyNotifer < ApplicationNotifier
5
+ # deliver_by :<%= file_path %>, class: "<%= class_name %>"
6
+ # end
7
+
8
+ # Specify required options for the deliver_by config block
9
+ # required_options :foo, :bar
10
+
2
11
  def deliver
3
12
  # Logic for sending the notification
4
13
  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
14
  end
@@ -1,8 +1,8 @@
1
1
  # To deliver this notification:
2
2
  #
3
- # <%= class_name %>.with(record: @post, message: "New post").deliver(User.all)
3
+ # <%= class_name %>Notifier.with(record: @post, message: "New post").deliver(User.all)
4
4
 
5
- class <%= class_name %> < Noticed::Event
5
+ class <%= class_name %>Notifier < ApplicationNotifier
6
6
  # Add your delivery methods
7
7
  #
8
8
  # deliver_by :email do |config|
@@ -21,4 +21,10 @@ class <%= class_name %> < Noticed::Event
21
21
  # Add required params
22
22
  #
23
23
  # required_param :message
24
+
25
+ # Compute recipients without having to pass them in
26
+ #
27
+ # recipients do
28
+ # params[:record].thread.all_authors
29
+ # end
24
30
  end
@@ -28,7 +28,9 @@ module Noticed
28
28
  if (json = args.delete(:json))
29
29
  request.body = json.to_json
30
30
  elsif (form = args.delete(:form))
31
- request.set_form(form, "multipart/form-data")
31
+ request.form_data = form
32
+ elsif (body = args.delete(:body))
33
+ request.body = body
32
34
  end
33
35
 
34
36
  logger.debug("POST #{url}")
@@ -1,20 +1,32 @@
1
1
  module Noticed
2
- class BulkDeliveryMethod < ApplicationJob
2
+ class BulkDeliveryMethod < Noticed.parent_class.constantize
3
3
  include ApiClient
4
4
  include RequiredOptions
5
5
 
6
+ extend ActiveModel::Callbacks
7
+
8
+ define_model_callbacks :deliver
9
+
6
10
  class_attribute :logger, default: Rails.logger
7
11
 
8
12
  attr_reader :config, :event
9
13
 
10
- def perform(delivery_method_name, event)
11
- @event = event
12
- @config = event.bulk_delivery_methods.fetch(delivery_method_name).config
14
+ def perform(delivery_method_name, event, recipient: nil, params: {}, overrides: {})
15
+ # Ephemeral notifications
16
+ if event.is_a? String
17
+ @event = event.constantize.new_with_params(recipient, params)
18
+ @config = overrides
19
+ else
20
+ @event = event
21
+ @config = event.bulk_delivery_methods.fetch(delivery_method_name).config.merge(overrides)
22
+ end
13
23
 
14
24
  return false if config.has_key?(:if) && !evaluate_option(:if)
15
25
  return false if config.has_key?(:unless) && evaluate_option(:unless)
16
26
 
17
- deliver
27
+ run_callbacks :deliver do
28
+ deliver
29
+ end
18
30
  end
19
31
 
20
32
  def deliver
@@ -23,7 +35,7 @@ module Noticed
23
35
 
24
36
  def fetch_constant(name)
25
37
  option = config[name]
26
- option.is_a?(String) ? option.constantize : option
38
+ option.is_a?(String) ? option.constantize : evaluate_option(option)
27
39
  end
28
40
 
29
41
  def evaluate_option(name)
@@ -34,7 +46,7 @@ module Noticed
34
46
  event.instance_exec(&option)
35
47
 
36
48
  # Call method if symbol and matching method
37
- elsif option.is_a?(Symbol) && event.respond_to?(option)
49
+ elsif option.is_a?(Symbol) && event.respond_to?(option, true)
38
50
  event.send(option)
39
51
 
40
52
  # Return the value