active_delivery 1.0.0.rc2 → 1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -23
- data/README.md +106 -6
- data/lib/.rbnext/3.0/abstract_notifier/async_adapters/active_job.rb +27 -0
- data/lib/.rbnext/3.0/active_delivery/base.rb +142 -18
- data/lib/.rbnext/3.0/active_delivery/callbacks.rb +21 -17
- data/lib/.rbnext/3.0/active_delivery/lines/base.rb +39 -13
- data/lib/.rbnext/3.0/active_delivery/lines/mailer.rb +2 -1
- data/lib/.rbnext/3.0/active_delivery/testing.rb +62 -0
- data/lib/.rbnext/3.1/abstract_notifier/base.rb +217 -0
- data/lib/.rbnext/3.1/active_delivery/base.rb +140 -16
- data/lib/.rbnext/3.1/active_delivery/lines/base.rb +39 -13
- data/lib/abstract_notifier/async_adapters/active_job.rb +4 -4
- data/lib/abstract_notifier/base.rb +57 -18
- data/lib/abstract_notifier/callbacks.rb +94 -0
- data/lib/abstract_notifier/testing.rb +8 -4
- data/lib/abstract_notifier/version.rb +1 -1
- data/lib/abstract_notifier.rb +1 -0
- data/lib/active_delivery/lines/base.rb +20 -1
- data/lib/active_delivery/lines/notifier.rb +1 -1
- data/lib/active_delivery/version.rb +1 -1
- metadata +9 -5
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveDelivery
|
4
|
+
module TestDelivery
|
5
|
+
class << self
|
6
|
+
def enable
|
7
|
+
raise ArgumentError, "block is required" unless block_given?
|
8
|
+
begin
|
9
|
+
clear
|
10
|
+
Thread.current.thread_variable_set(:active_delivery_testing, true)
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
Thread.current.thread_variable_set(:active_delivery_testing, false)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def enabled?
|
18
|
+
Thread.current.thread_variable_get(:active_delivery_testing) == true
|
19
|
+
end
|
20
|
+
|
21
|
+
def track(delivery, options)
|
22
|
+
store << [delivery, options]
|
23
|
+
end
|
24
|
+
|
25
|
+
def track_line(line)
|
26
|
+
lines << line
|
27
|
+
end
|
28
|
+
|
29
|
+
def store
|
30
|
+
Thread.current.thread_variable_get(:active_delivery_testing_store) || Thread.current.thread_variable_set(:active_delivery_testing_store, [])
|
31
|
+
end
|
32
|
+
|
33
|
+
def lines
|
34
|
+
Thread.current.thread_variable_get(:active_delivery_testing_lines) || Thread.current.thread_variable_set(:active_delivery_testing_lines, [])
|
35
|
+
end
|
36
|
+
|
37
|
+
def clear
|
38
|
+
store.clear
|
39
|
+
lines.clear
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def perform_notify(delivery, **options)
|
44
|
+
return super unless test?
|
45
|
+
TestDelivery.track(delivery, options)
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def notify_line(line, *__rest__, &__block__)
|
50
|
+
res = super
|
51
|
+
TestDelivery.track_line(line) if res
|
52
|
+
end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :notify_line)
|
53
|
+
|
54
|
+
def test?
|
55
|
+
TestDelivery.enabled?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
ActiveDelivery::Base.prepend ActiveDelivery::TestDelivery
|
61
|
+
|
62
|
+
require "active_delivery/testing/rspec" if defined?(RSpec::Core)
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AbstractNotifier
|
4
|
+
# NotificationDelivery payload wrapper which contains
|
5
|
+
# information about the current notifier class
|
6
|
+
# and knows how to trigger the delivery
|
7
|
+
class NotificationDelivery
|
8
|
+
attr_reader :action_name
|
9
|
+
|
10
|
+
def initialize(owner_class, action_name, params: {}, args: [], kwargs: {})
|
11
|
+
@owner_class = owner_class
|
12
|
+
@action_name = action_name
|
13
|
+
@params = params
|
14
|
+
@args = args
|
15
|
+
@kwargs = kwargs
|
16
|
+
end
|
17
|
+
|
18
|
+
def processed
|
19
|
+
return @processed if instance_variable_defined?(:@processed)
|
20
|
+
|
21
|
+
@processed = notifier.process_action(action_name, *args, **kwargs) || Notification.new(nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :notification, :processed
|
25
|
+
|
26
|
+
def notify_later
|
27
|
+
owner_class.async_adapter.enqueue(owner_class.name, action_name, params: params, args: args, kwargs: kwargs)
|
28
|
+
end
|
29
|
+
|
30
|
+
def notify_now
|
31
|
+
return unless notification.payload
|
32
|
+
|
33
|
+
notifier.deliver!(notification)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :owner_class, :params, :args, :kwargs
|
39
|
+
|
40
|
+
def notifier
|
41
|
+
@notifier ||= owner_class.new(action_name, **params)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Notification object contains the compiled payload to be delivered
|
46
|
+
class Notification
|
47
|
+
attr_reader :payload
|
48
|
+
|
49
|
+
def initialize(payload)
|
50
|
+
@payload = payload
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Base class for notifiers
|
55
|
+
class Base
|
56
|
+
class ParamsProxy
|
57
|
+
attr_reader :notifier_class, :params
|
58
|
+
|
59
|
+
def initialize(notifier_class, params)
|
60
|
+
@notifier_class = notifier_class
|
61
|
+
@params = params
|
62
|
+
end
|
63
|
+
|
64
|
+
# rubocop:disable Style/MethodMissingSuper
|
65
|
+
def method_missing(method_name, *args, **kwargs)
|
66
|
+
NotificationDelivery.new(notifier_class, method_name, params: params, args: args, kwargs: kwargs)
|
67
|
+
end
|
68
|
+
# rubocop:enable Style/MethodMissingSuper
|
69
|
+
|
70
|
+
def respond_to_missing?(*args)
|
71
|
+
notifier_class.respond_to_missing?(*args)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class << self
|
76
|
+
attr_writer :driver
|
77
|
+
|
78
|
+
def driver
|
79
|
+
return @driver if instance_variable_defined?(:@driver)
|
80
|
+
|
81
|
+
@driver =
|
82
|
+
if superclass.respond_to?(:driver)
|
83
|
+
superclass.driver
|
84
|
+
else
|
85
|
+
raise "Driver not found for #{name}. " \
|
86
|
+
"Please, specify driver via `self.driver = MyDriver`"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def async_adapter=(args)
|
91
|
+
adapter, options = Array(args)
|
92
|
+
@async_adapter = AsyncAdapters.lookup(adapter, options)
|
93
|
+
end
|
94
|
+
|
95
|
+
def async_adapter
|
96
|
+
return @async_adapter if instance_variable_defined?(:@async_adapter)
|
97
|
+
|
98
|
+
@async_adapter =
|
99
|
+
if superclass.respond_to?(:async_adapter)
|
100
|
+
superclass.async_adapter
|
101
|
+
else
|
102
|
+
AbstractNotifier.async_adapter
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def default(method_name = nil, **hargs, &block)
|
107
|
+
return @defaults_generator = block if block
|
108
|
+
|
109
|
+
return @defaults_generator = proc { send(method_name) } unless method_name.nil?
|
110
|
+
|
111
|
+
@default_params =
|
112
|
+
if superclass.respond_to?(:default_params)
|
113
|
+
superclass.default_params.merge(hargs).freeze
|
114
|
+
else
|
115
|
+
hargs.freeze
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def defaults_generator
|
120
|
+
return @defaults_generator if instance_variable_defined?(:@defaults_generator)
|
121
|
+
|
122
|
+
@defaults_generator =
|
123
|
+
if superclass.respond_to?(:defaults_generator)
|
124
|
+
superclass.defaults_generator
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def default_params
|
129
|
+
return @default_params if instance_variable_defined?(:@default_params)
|
130
|
+
|
131
|
+
@default_params =
|
132
|
+
if superclass.respond_to?(:default_params)
|
133
|
+
superclass.default_params.dup
|
134
|
+
else
|
135
|
+
{}
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def method_missing(method_name, *args, **kwargs)
|
140
|
+
if action_methods.include?(method_name.to_s)
|
141
|
+
NotificationDelivery.new(self, method_name, args: args, kwargs: kwargs)
|
142
|
+
else
|
143
|
+
super
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def with(params)
|
148
|
+
ParamsProxy.new(self, params)
|
149
|
+
end
|
150
|
+
|
151
|
+
def respond_to_missing?(method_name, _include_private = false)
|
152
|
+
action_methods.include?(method_name.to_s) || super
|
153
|
+
end
|
154
|
+
|
155
|
+
# See https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/actionpack/lib/abstract_controller/base.rb#L74
|
156
|
+
def action_methods
|
157
|
+
@action_methods ||= begin
|
158
|
+
# All public instance methods of this class, including ancestors
|
159
|
+
methods = (public_instance_methods(true) -
|
160
|
+
# Except for public instance methods of Base and its ancestors
|
161
|
+
Base.public_instance_methods(true) +
|
162
|
+
# Be sure to include shadowed public instance methods of this class
|
163
|
+
public_instance_methods(false))
|
164
|
+
|
165
|
+
methods.map!(&:to_s)
|
166
|
+
|
167
|
+
methods.to_set
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
attr_reader :params, :notification_name
|
173
|
+
|
174
|
+
def initialize(notification_name, **params)
|
175
|
+
@notification_name = notification_name
|
176
|
+
@params = params.freeze
|
177
|
+
end
|
178
|
+
|
179
|
+
def process_action(...)
|
180
|
+
public_send(...)
|
181
|
+
end; respond_to?(:ruby2_keywords, true) && (ruby2_keywords :process_action)
|
182
|
+
|
183
|
+
def deliver!(notification)
|
184
|
+
self.class.driver.call(notification.payload)
|
185
|
+
end
|
186
|
+
|
187
|
+
def notification(**payload)
|
188
|
+
merge_defaults!(payload)
|
189
|
+
|
190
|
+
payload[:body] = implicit_payload_body unless payload.key?(:body)
|
191
|
+
|
192
|
+
raise ArgumentError, "Notification body must be present" if
|
193
|
+
payload[:body].nil? || payload[:body].empty?
|
194
|
+
|
195
|
+
@notification = Notification.new(payload)
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
|
200
|
+
def implicit_payload_body
|
201
|
+
# no-op — override to provide custom logic
|
202
|
+
end
|
203
|
+
|
204
|
+
def merge_defaults!(payload)
|
205
|
+
defaults =
|
206
|
+
if self.class.defaults_generator
|
207
|
+
instance_exec(&self.class.defaults_generator)
|
208
|
+
else
|
209
|
+
self.class.default_params
|
210
|
+
end
|
211
|
+
|
212
|
+
defaults.each do |k, v|
|
213
|
+
payload[k] = v unless payload.key?(k)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -1,6 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveDelivery
|
4
|
+
class Delivery # :nodoc:
|
5
|
+
attr_reader :params, :options, :metadata, :notification, :owner
|
6
|
+
|
7
|
+
def initialize(owner, notification:, params:, options:, metadata:)
|
8
|
+
@owner = owner
|
9
|
+
@notification = notification
|
10
|
+
@params = params.freeze
|
11
|
+
@options = options.freeze
|
12
|
+
@metadata = metadata.freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
def deliver_later = owner.perform_notify(self)
|
16
|
+
|
17
|
+
def deliver_now = owner.perform_notify(self, sync: true)
|
18
|
+
|
19
|
+
def delivery_class = owner.class
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
# Whether to memoize resolved handler classes or not.
|
24
|
+
# Set to false if you're using a code reloader (e.g., Zeitwerk).
|
25
|
+
#
|
26
|
+
# Defaults to true (i.e. memoization is enabled
|
27
|
+
attr_accessor :cache_classes
|
28
|
+
# Whether to enforce specifying available delivery actions via .delivers in the
|
29
|
+
# delivery classes
|
30
|
+
attr_accessor :deliver_actions_required
|
31
|
+
end
|
32
|
+
|
33
|
+
self.cache_classes = true
|
34
|
+
self.deliver_actions_required = false
|
35
|
+
|
4
36
|
# Base class for deliveries.
|
5
37
|
#
|
6
38
|
# Delivery object describes how to notify a user about
|
@@ -10,6 +42,8 @@ module ActiveDelivery
|
|
10
42
|
# (i.e. mailers, notifiers). That means that calling a method on delivery class invokes the
|
11
43
|
# same method on the corresponding class, e.g.:
|
12
44
|
#
|
45
|
+
# EventsDelivery.one_hour_before(profile, event).deliver_later
|
46
|
+
# # or
|
13
47
|
# EventsDelivery.notify(:one_hour_before, profile, event)
|
14
48
|
#
|
15
49
|
# # under the hood it calls
|
@@ -20,14 +54,14 @@ module ActiveDelivery
|
|
20
54
|
#
|
21
55
|
# Delivery also supports _parameterized_ calling:
|
22
56
|
#
|
23
|
-
# EventsDelivery.with(profile: profile).
|
57
|
+
# EventsDelivery.with(profile: profile).canceled(event).deliver_later
|
24
58
|
#
|
25
59
|
# The parameters could be accessed through `params` instance method (e.g.
|
26
60
|
# to implement guard-like logic).
|
27
61
|
#
|
28
62
|
# When params are presents the parametrized mailer is used, i.e.:
|
29
63
|
#
|
30
|
-
# EventsMailer.with(profile: profile).canceled(event)
|
64
|
+
# EventsMailer.with(profile: profile).canceled(event).deliver_later
|
31
65
|
#
|
32
66
|
# See https://api.rubyonrails.org/classes/ActionMailer/Parameterized.html
|
33
67
|
class Base
|
@@ -47,6 +81,8 @@ module ActiveDelivery
|
|
47
81
|
notify(mid, *args, **hargs, sync: true)
|
48
82
|
end
|
49
83
|
|
84
|
+
alias_method :notify_now, :notify!
|
85
|
+
|
50
86
|
def delivery_lines
|
51
87
|
@lines ||= if superclass.respond_to?(:delivery_lines)
|
52
88
|
superclass.delivery_lines.each_with_object({}) do |(key, val), acc|
|
@@ -57,12 +93,19 @@ module ActiveDelivery
|
|
57
93
|
end
|
58
94
|
end
|
59
95
|
|
60
|
-
def register_line(line_id, line_class, **options)
|
96
|
+
def register_line(line_id, line_class = nil, notifier: nil, **options)
|
97
|
+
raise ArgumentError, "A line class or notifier configuration must be provided" if line_class.nil? && notifier.nil?
|
98
|
+
|
99
|
+
# Configure Notifier
|
100
|
+
if line_class.nil?
|
101
|
+
line_class = ActiveDelivery::Lines::Notifier
|
102
|
+
end
|
103
|
+
|
61
104
|
delivery_lines[line_id] = line_class.new(id: line_id, owner: self, **options)
|
62
105
|
|
63
106
|
instance_eval <<~CODE, __FILE__, __LINE__ + 1
|
64
107
|
def #{line_id}(val)
|
65
|
-
delivery_lines[:#{line_id}].
|
108
|
+
delivery_lines[:#{line_id}].handler_class_name = val
|
66
109
|
end
|
67
110
|
|
68
111
|
def #{line_id}_class
|
@@ -81,8 +124,46 @@ module ActiveDelivery
|
|
81
124
|
end
|
82
125
|
|
83
126
|
def abstract_class? = abstract_class == true
|
127
|
+
|
128
|
+
# Specify explicitly which actions are supported by the delivery.
|
129
|
+
def delivers(*actions)
|
130
|
+
actions.each do |mid|
|
131
|
+
class_eval <<~CODE, __FILE__, __LINE__ + 1
|
132
|
+
def self.#{mid}(...)
|
133
|
+
new.#{mid}(...)
|
134
|
+
end
|
135
|
+
|
136
|
+
def #{mid}(*args, **kwargs)
|
137
|
+
delivery(
|
138
|
+
notification: :#{mid},
|
139
|
+
params: args,
|
140
|
+
options: kwargs
|
141
|
+
)
|
142
|
+
end
|
143
|
+
CODE
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def respond_to_missing?(mid, include_private = false)
|
148
|
+
unless ActiveDelivery.deliver_actions_required
|
149
|
+
return true if delivery_lines.any? { |_, line| line.notify?(mid) }
|
150
|
+
end
|
151
|
+
|
152
|
+
super
|
153
|
+
end
|
154
|
+
|
155
|
+
def method_missing(mid, *args, **kwargs)
|
156
|
+
return super unless respond_to_missing?(mid)
|
157
|
+
|
158
|
+
# Lazily define a class method to avoid lookups
|
159
|
+
delivers(mid)
|
160
|
+
|
161
|
+
public_send(mid, *args, **kwargs)
|
162
|
+
end
|
84
163
|
end
|
85
164
|
|
165
|
+
self.abstract_class = true
|
166
|
+
|
86
167
|
attr_reader :params, :notification_name
|
87
168
|
|
88
169
|
def initialize(**params)
|
@@ -91,30 +172,73 @@ module ActiveDelivery
|
|
91
172
|
end
|
92
173
|
|
93
174
|
# Enqueues delivery (i.e. uses #deliver_later for mailers)
|
94
|
-
def notify(mid,
|
95
|
-
|
96
|
-
|
175
|
+
def notify(mid, *args, **kwargs)
|
176
|
+
perform_notify(
|
177
|
+
delivery(notification: mid, params: args, options: kwargs)
|
178
|
+
)
|
97
179
|
end
|
98
180
|
|
99
181
|
# The same as .notify but delivers synchronously
|
100
182
|
# (i.e. #deliver_now for mailers)
|
101
|
-
def notify!(mid, *args, **
|
102
|
-
|
183
|
+
def notify!(mid, *args, **kwargs)
|
184
|
+
perform_notify(
|
185
|
+
delivery(notification: mid, params: args, options: kwargs),
|
186
|
+
sync: true
|
187
|
+
)
|
103
188
|
end
|
104
189
|
|
105
|
-
|
190
|
+
alias_method :notify_now, :notify!
|
191
|
+
|
192
|
+
def respond_to_missing?(mid, include_private = false)
|
193
|
+
unless ActiveDelivery.deliver_actions_required
|
194
|
+
return true if delivery_lines.any? { |_, line| line.notify?(mid) }
|
195
|
+
end
|
196
|
+
|
197
|
+
super
|
198
|
+
end
|
106
199
|
|
107
|
-
def
|
200
|
+
def method_missing(mid, *args, **kwargs)
|
201
|
+
return super unless respond_to_missing?(mid)
|
202
|
+
|
203
|
+
# Lazily define a method to avoid future lookups
|
204
|
+
self.class.class_eval <<~CODE, __FILE__, __LINE__ + 1
|
205
|
+
def #{mid}(*args, **kwargs)
|
206
|
+
delivery(
|
207
|
+
notification: :#{mid},
|
208
|
+
params: args,
|
209
|
+
options: kwargs
|
210
|
+
)
|
211
|
+
end
|
212
|
+
CODE
|
213
|
+
|
214
|
+
public_send(mid, *args, **kwargs)
|
215
|
+
end
|
216
|
+
|
217
|
+
protected
|
218
|
+
|
219
|
+
def perform_notify(delivery, sync: false)
|
108
220
|
delivery_lines.each do |type, line|
|
109
|
-
next
|
110
|
-
next unless line.notify?(notification_name)
|
221
|
+
next unless line.notify?(delivery.notification)
|
111
222
|
|
112
|
-
notify_line(type,
|
223
|
+
notify_line(type, line, delivery, sync: sync)
|
113
224
|
end
|
114
225
|
end
|
115
226
|
|
116
|
-
|
117
|
-
|
227
|
+
private
|
228
|
+
|
229
|
+
def notify_line(type, line, delivery, sync:)
|
230
|
+
line.notify(
|
231
|
+
delivery.notification,
|
232
|
+
*delivery.params,
|
233
|
+
params: params,
|
234
|
+
sync: sync,
|
235
|
+
**delivery.options
|
236
|
+
)
|
237
|
+
true
|
238
|
+
end
|
239
|
+
|
240
|
+
def delivery(notification:, params: nil, options: nil, metadata: nil)
|
241
|
+
Delivery.new(self, notification: notification, params: params, options: options, metadata: metadata)
|
118
242
|
end
|
119
243
|
|
120
244
|
def delivery_lines
|
@@ -1,17 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
unless "".respond_to?(:safe_constantize)
|
4
|
+
require "active_delivery/ext/string_constantize"
|
5
|
+
using ActiveDelivery::Ext::StringConstantize
|
6
|
+
end
|
7
|
+
|
3
8
|
module ActiveDelivery
|
4
9
|
module Lines
|
5
10
|
class Base
|
6
11
|
attr_reader :id, :options
|
7
12
|
attr_accessor :owner
|
8
|
-
|
13
|
+
attr_accessor :handler_class_name
|
9
14
|
|
10
15
|
def initialize(id:, owner:, **options)
|
11
16
|
@id = id
|
12
17
|
@owner = owner
|
13
18
|
@options = options.tap(&:freeze)
|
14
|
-
@resolver = options[:resolver]
|
19
|
+
@resolver = options[:resolver] || build_pattern_resolver(options[:resolver_pattern])
|
15
20
|
end
|
16
21
|
|
17
22
|
def dup_for(new_owner)
|
@@ -23,7 +28,7 @@ module ActiveDelivery
|
|
23
28
|
end
|
24
29
|
|
25
30
|
def notify?(method_name)
|
26
|
-
handler_class
|
31
|
+
handler_class&.respond_to?(method_name)
|
27
32
|
end
|
28
33
|
|
29
34
|
def notify_now(handler, mid, ...)
|
@@ -38,26 +43,47 @@ module ActiveDelivery
|
|
38
43
|
end
|
39
44
|
|
40
45
|
def handler_class
|
41
|
-
|
46
|
+
if ::ActiveDelivery.cache_classes
|
47
|
+
return @handler_class if instance_variable_defined?(:@handler_class)
|
48
|
+
end
|
42
49
|
|
43
50
|
return @handler_class = nil if owner.abstract_class?
|
44
51
|
|
45
|
-
|
46
|
-
|
52
|
+
superline = owner.superclass.delivery_lines[id] if owner.superclass.respond_to?(:delivery_lines) && owner.superclass.delivery_lines[id]
|
53
|
+
|
54
|
+
# If an explicit class name has been specified somewhere in the ancestor chain, use it.
|
55
|
+
class_name = @handler_class_name || superline&.handler_class_name
|
56
|
+
|
57
|
+
@handler_class =
|
58
|
+
if class_name
|
59
|
+
class_name.is_a?(Class) ? class_name : class_name.safe_constantize
|
60
|
+
else
|
61
|
+
resolve_class(owner) || superline&.handler_class
|
62
|
+
end
|
47
63
|
end
|
48
64
|
|
49
65
|
private
|
50
66
|
|
51
|
-
|
52
|
-
handler_method = "#{id}_class"
|
67
|
+
attr_reader :resolver
|
53
68
|
|
54
|
-
|
55
|
-
return unless
|
69
|
+
def build_pattern_resolver(pattern)
|
70
|
+
return unless pattern
|
56
71
|
|
57
|
-
|
58
|
-
|
72
|
+
proc do |delivery|
|
73
|
+
delivery_class = delivery.name
|
59
74
|
|
60
|
-
|
75
|
+
next unless delivery_class
|
76
|
+
|
77
|
+
*namespace, delivery_name = delivery_class.split("::")
|
78
|
+
|
79
|
+
delivery_namespace = ""
|
80
|
+
delivery_namespace = "#{namespace.join("::")}::" unless namespace.empty?
|
81
|
+
|
82
|
+
delivery_name = delivery_name.sub(/Delivery$/, "")
|
83
|
+
|
84
|
+
(pattern % {delivery_class: delivery_class, delivery_name: delivery_name, delivery_namespace: delivery_namespace}).safe_constantize
|
85
|
+
end
|
86
|
+
end
|
61
87
|
end
|
62
88
|
end
|
63
89
|
end
|
@@ -4,8 +4,8 @@ module AbstractNotifier
|
|
4
4
|
module AsyncAdapters
|
5
5
|
class ActiveJob
|
6
6
|
class DeliveryJob < ::ActiveJob::Base
|
7
|
-
def perform(notifier_class,
|
8
|
-
AbstractNotifier::
|
7
|
+
def perform(notifier_class, ...)
|
8
|
+
AbstractNotifier::NotificationDelivery.new(notifier_class.constantize, ...).notify_now
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -17,8 +17,8 @@ module AbstractNotifier
|
|
17
17
|
@job = job.set(queue: queue)
|
18
18
|
end
|
19
19
|
|
20
|
-
def enqueue(
|
21
|
-
job.perform_later(
|
20
|
+
def enqueue(...)
|
21
|
+
job.perform_later(...)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|