mime_actor 0.6.2 → 0.6.3.alpha
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/lib/mime_actor/action.rb +8 -3
- data/lib/mime_actor/callbacks.rb +201 -0
- data/lib/mime_actor/dispatcher.rb +11 -12
- data/lib/mime_actor/rescue.rb +5 -19
- data/lib/mime_actor/scene.rb +5 -13
- data/lib/mime_actor/stage.rb +11 -26
- data/lib/mime_actor/validator.rb +15 -1
- data/lib/mime_actor/version.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5221de8b1d1149a88de730ab8e6c6c764a22e7067b9e57b6265ce801c671ce3f
|
4
|
+
data.tar.gz: e98f9d6f3e5a8aa04f16cf77921edad0b4a61893ddb3c019157885079462fcde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f6ce7e70ab30a4be726f346beb517c8036c95a1d516c3012d9ed62723a14c130d4af05cdf3695244f5fcb56d33f83cf719369ead9d05eabeba89e5335de1f3a
|
7
|
+
data.tar.gz: 90e8ca69ac9ff99e9813c1dac19bc0826893f106968bb6c6684201a84523b13ab9df225fd597daf96379825080f9164ecfb19a6f7b48c8eabf217e5411654530
|
data/lib/mime_actor/action.rb
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
# :markup: markdown
|
4
4
|
|
5
|
+
require "mime_actor/callbacks"
|
6
|
+
require "mime_actor/logging"
|
5
7
|
require "mime_actor/scene"
|
6
8
|
require "mime_actor/stage"
|
7
|
-
require "mime_actor/rescue"
|
8
9
|
|
9
10
|
require "active_support/concern"
|
10
11
|
require "active_support/core_ext/object/blank"
|
@@ -25,9 +26,9 @@ module MimeActor
|
|
25
26
|
include AbstractController::Rendering # required by MimeResponds
|
26
27
|
include ActionController::MimeResponds
|
27
28
|
|
29
|
+
include Callbacks
|
28
30
|
include Scene
|
29
31
|
include Stage
|
30
|
-
include Rescue
|
31
32
|
include Logging
|
32
33
|
|
33
34
|
# The core logic where rendering logics are collected as `Proc` and passed over to `ActionController::MimeResponds`
|
@@ -55,7 +56,11 @@ module MimeActor
|
|
55
56
|
|
56
57
|
respond_to do |collector|
|
57
58
|
formats.each do |format, actor|
|
58
|
-
dispatch =
|
59
|
+
dispatch = lambda do
|
60
|
+
run_act_callbacks(format) do
|
61
|
+
cue_actor(actor.presence || "#{action}_#{format}", action:, format:)
|
62
|
+
end
|
63
|
+
end
|
59
64
|
collector.public_send(format, &dispatch)
|
60
65
|
end
|
61
66
|
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "mime_actor/validator"
|
6
|
+
|
7
|
+
require "active_support/callbacks"
|
8
|
+
require "active_support/concern"
|
9
|
+
require "active_support/core_ext/array/wrap"
|
10
|
+
require "active_support/core_ext/object/blank"
|
11
|
+
|
12
|
+
module MimeActor
|
13
|
+
# # MimeActor Callbacks
|
14
|
+
#
|
15
|
+
# MimeActor provides hooks during the life cycle of an act. Available callbacks are:
|
16
|
+
#
|
17
|
+
# - before_act
|
18
|
+
# - around_act
|
19
|
+
# - after_act
|
20
|
+
#
|
21
|
+
# NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
|
22
|
+
#
|
23
|
+
module Callbacks
|
24
|
+
extend ActiveSupport::Concern
|
25
|
+
|
26
|
+
include ActiveSupport::Callbacks
|
27
|
+
include MimeActor::Validator
|
28
|
+
|
29
|
+
included do
|
30
|
+
define_callbacks :act, skip_after_callbacks_if_terminated: true
|
31
|
+
|
32
|
+
%i[before after around].each { |kind| define_act_callbacks(kind) }
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
class ActionMatcher
|
37
|
+
def initialize(actions)
|
38
|
+
@actions = Array.wrap(actions).to_set(&:to_s)
|
39
|
+
end
|
40
|
+
|
41
|
+
def match?(controller)
|
42
|
+
@actions.include?(controller.action_name)
|
43
|
+
end
|
44
|
+
|
45
|
+
alias after match?
|
46
|
+
alias before match?
|
47
|
+
alias around match?
|
48
|
+
end
|
49
|
+
|
50
|
+
def callback_chain_name(format = nil)
|
51
|
+
if format.present?
|
52
|
+
validate!(:format, format)
|
53
|
+
:"act_#{format}"
|
54
|
+
else
|
55
|
+
:act
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def callback_chain_defined?(name)
|
60
|
+
!!get_callbacks(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def define_callback_chain(name)
|
66
|
+
return if callback_chain_defined?(name)
|
67
|
+
|
68
|
+
define_callbacks name, skip_after_callbacks_if_terminated: true
|
69
|
+
end
|
70
|
+
|
71
|
+
def configure_callbacks(callbacks, actions, formats, block)
|
72
|
+
options = {}
|
73
|
+
options[:if] = ActionMatcher.new(actions) if actions.present?
|
74
|
+
callbacks.push(block) if block
|
75
|
+
|
76
|
+
formats = Array.wrap(formats)
|
77
|
+
formats << nil if formats.empty?
|
78
|
+
|
79
|
+
callbacks.each do |callback|
|
80
|
+
formats.each do |format|
|
81
|
+
chain = callback_chain_name(format)
|
82
|
+
define_callback_chain(chain)
|
83
|
+
yield chain, callback, options
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def validate_callback_options!(action, format)
|
89
|
+
validate!(:action_or_actions, action) if action.present?
|
90
|
+
validate!(:format_or_formats, format) if format.present?
|
91
|
+
end
|
92
|
+
|
93
|
+
def define_act_callbacks(kind)
|
94
|
+
module_eval(
|
95
|
+
# def self.before_act(*callbacks, action: nil, format: nil, &block)
|
96
|
+
# validate_callback_options!(action, format)
|
97
|
+
# configure_callbacks(callbacks, action, format, block) do |chain, callback, options|
|
98
|
+
# set_callback(chain, :before, callback, options)
|
99
|
+
# end
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# def self.prepend_before_act(*callbacks, action: nil, format: nil, &block)
|
103
|
+
# validate_callback_options!(action, format)
|
104
|
+
# configure_callbacks(callbacks, action, format, block) do |chain, callback, options|
|
105
|
+
# set_callback(chain, :before, callback, options.merge!(prepend: true))
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
<<-RUBY, __FILE__, __LINE__ + 1
|
109
|
+
def self.#{kind}_act(*callbacks, action: nil, format: nil, &block)
|
110
|
+
validate_callback_options!(action, format)
|
111
|
+
configure_callbacks(callbacks, action, format, block) do |chain, callback, options|
|
112
|
+
set_callback(chain, :#{kind}, callback, options)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.prepend_#{kind}_act(*callbacks, action: nil, format: nil, &block)
|
117
|
+
validate_callback_options!(action, format)
|
118
|
+
configure_callbacks(callbacks, action, format, block) do |chain, callback, options|
|
119
|
+
set_callback(chain, :#{kind}, callback, options.merge!(prepend: true))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
RUBY
|
123
|
+
)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Callbacks invocation sequence depends on the order of callback definition.
|
128
|
+
# (except for callbacks with `format` filter).
|
129
|
+
#
|
130
|
+
# @example callbacks with/without action filter
|
131
|
+
# before_act :my_before_act_one
|
132
|
+
# before_act :my_before_act_two, action: :create
|
133
|
+
# before_act :my_before_act_three
|
134
|
+
#
|
135
|
+
# around_act :my_around_act_one
|
136
|
+
# around_act :my_around_act_two, action: :create
|
137
|
+
# around_act :my_around_act_three
|
138
|
+
#
|
139
|
+
# after_act :my_after_act_one
|
140
|
+
# after_act :my_after_act_two, action: :create
|
141
|
+
# after_act :my_after_act_three
|
142
|
+
#
|
143
|
+
# # actual sequence:
|
144
|
+
# # - my_before_act_one
|
145
|
+
# # - my_before_act_two
|
146
|
+
# # - my_before_act_three
|
147
|
+
# # - my_around_act_one
|
148
|
+
# # - my_around_act_two
|
149
|
+
# # - my_around_act_three
|
150
|
+
# # - my_after_act_three
|
151
|
+
# # - my_after_act_two
|
152
|
+
# # - my_after_act_one
|
153
|
+
#
|
154
|
+
# @example callbacks with format filter
|
155
|
+
# before_act :my_before_act_one
|
156
|
+
# before_act :my_before_act_two, action: :create
|
157
|
+
# before_act :my_before_act_three, action: :create, format: :html
|
158
|
+
# before_act :my_before_act_four
|
159
|
+
#
|
160
|
+
# around_act :my_around_act_one
|
161
|
+
# around_act :my_around_act_two, action: :create, format: :html
|
162
|
+
# around_act :my_around_act_three, action: :create
|
163
|
+
# around_act :my_around_act_four
|
164
|
+
#
|
165
|
+
# after_act :my_after_act_one, format: :html
|
166
|
+
# after_act :my_after_act_two
|
167
|
+
# after_act :my_after_act_three, action: :create
|
168
|
+
# after_act :my_after_act_four
|
169
|
+
#
|
170
|
+
# # actual sequence:
|
171
|
+
# # - my_before_act_one
|
172
|
+
# # - my_before_act_two
|
173
|
+
# # - my_before_act_four
|
174
|
+
# # - my_around_act_one
|
175
|
+
# # - my_around_act_three
|
176
|
+
# # - my_around_act_four
|
177
|
+
# # - my_before_act_three
|
178
|
+
# # - my_around_act_two
|
179
|
+
# # - my_after_act_one
|
180
|
+
# # - my_after_act_four
|
181
|
+
# # - my_after_act_three
|
182
|
+
# # - my_after_act_two
|
183
|
+
#
|
184
|
+
def run_act_callbacks(format)
|
185
|
+
action_chain = self.class.callback_chain_name
|
186
|
+
format_chain = self.class.callback_chain_name(format)
|
187
|
+
|
188
|
+
if self.class.callback_chain_defined?(format_chain)
|
189
|
+
run_callbacks action_chain do
|
190
|
+
run_callbacks format_chain do
|
191
|
+
yield if block_given?
|
192
|
+
end
|
193
|
+
end
|
194
|
+
else
|
195
|
+
run_callbacks action_chain do
|
196
|
+
yield if block_given?
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
# :markup: markdown
|
4
4
|
|
5
|
+
require "mime_actor/errors"
|
6
|
+
|
5
7
|
module MimeActor
|
6
8
|
module Dispatcher
|
7
9
|
class MethodCall
|
@@ -13,13 +15,12 @@ module MimeActor
|
|
13
15
|
validate!
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
18
|
+
def call(target)
|
19
|
+
raise MimeActor::ActorNotFound, method_name unless target.respond_to?(method_name)
|
20
|
+
|
21
|
+
method_call = target.method(method_name)
|
22
|
+
filtered_args = method_call.arity.negative? ? args : args.take(method_call.arity)
|
23
|
+
method_call.call(*filtered_args)
|
23
24
|
end
|
24
25
|
|
25
26
|
private
|
@@ -38,11 +39,9 @@ module MimeActor
|
|
38
39
|
validate!
|
39
40
|
end
|
40
41
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
target.instance_exec(*filtered_args, &block)
|
45
|
-
end
|
42
|
+
def call(target)
|
43
|
+
filtered_args = block.arity.negative? ? args : args.take(block.arity)
|
44
|
+
target.instance_exec(*filtered_args, &block)
|
46
45
|
end
|
47
46
|
|
48
47
|
private
|
data/lib/mime_actor/rescue.rb
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
|
5
5
|
require "mime_actor/dispatcher"
|
6
6
|
require "mime_actor/validator"
|
7
|
-
require "mime_actor/stage"
|
8
7
|
|
9
8
|
require "active_support/concern"
|
10
9
|
require "active_support/core_ext/array/wrap"
|
@@ -23,7 +22,6 @@ module MimeActor
|
|
23
22
|
module Rescue
|
24
23
|
extend ActiveSupport::Concern
|
25
24
|
|
26
|
-
include Stage
|
27
25
|
include Validator
|
28
26
|
|
29
27
|
included do
|
@@ -51,19 +49,11 @@ module MimeActor
|
|
51
49
|
raise ArgumentError, "error filter is required" if klazzes.empty?
|
52
50
|
raise ArgumentError, "provide either the with: argument or a block" unless with.present? ^ block_given?
|
53
51
|
|
54
|
-
if
|
55
|
-
|
56
|
-
else
|
57
|
-
validate!(:with, with)
|
58
|
-
end
|
59
|
-
|
60
|
-
if action.present?
|
61
|
-
action.is_a?(Enumerable) ? validate!(:actions, action) : validate!(:action, action)
|
62
|
-
end
|
52
|
+
validate!(:with, with) if with.present?
|
53
|
+
with = block if block_given?
|
63
54
|
|
64
|
-
if
|
65
|
-
|
66
|
-
end
|
55
|
+
validate!(:action_or_actions, action) if action.present?
|
56
|
+
validate!(:format_or_formats, format) if format.present?
|
67
57
|
|
68
58
|
klazzes.each do |klazz|
|
69
59
|
validate!(:klazz, klazz)
|
@@ -156,11 +146,7 @@ module MimeActor
|
|
156
146
|
visited << error
|
157
147
|
rescuer = find_rescuer(error, format:, action:)
|
158
148
|
if (dispatch = MimeActor::Dispatcher.build(rescuer, error, format, action))
|
159
|
-
|
160
|
-
result = catch(:abort) do
|
161
|
-
dispatch.to_callable.call(self).tap { dispatched = true }
|
162
|
-
end
|
163
|
-
logger.error { "rescue error, cause: #{result.inspect}" } unless dispatched
|
149
|
+
dispatch.call(self)
|
164
150
|
error
|
165
151
|
elsif error&.cause
|
166
152
|
rescue_actor(error.cause, format:, action:, visited:)
|
data/lib/mime_actor/scene.rb
CHANGED
@@ -86,20 +86,12 @@ module MimeActor
|
|
86
86
|
|
87
87
|
raise ArgumentError, "provide either the with: argument or a block" if with.present? && block_given?
|
88
88
|
|
89
|
-
if
|
90
|
-
|
91
|
-
elsif with.present?
|
92
|
-
validate!(:with, with)
|
93
|
-
end
|
89
|
+
validate!(:with, with) if with.present?
|
90
|
+
with = block if block_given?
|
94
91
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
when Symbol, String
|
99
|
-
validate!(:action, actions)
|
100
|
-
else
|
101
|
-
raise ArgumentError, "action is required"
|
102
|
-
end
|
92
|
+
raise ArgumentError, "action is required" unless (actions = on).present?
|
93
|
+
|
94
|
+
validate!(:action_or_actions, actions)
|
103
95
|
|
104
96
|
Array.wrap(actions).each do |action|
|
105
97
|
formats.each { |format| compose_scene(action, format, with) }
|
data/lib/mime_actor/stage.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
# :markup: markdown
|
4
4
|
|
5
|
-
require "mime_actor/errors"
|
6
5
|
require "mime_actor/dispatcher"
|
7
6
|
require "mime_actor/logging"
|
7
|
+
require "mime_actor/rescue"
|
8
8
|
|
9
9
|
require "active_support/concern"
|
10
10
|
require "active_support/core_ext/module/attribute_accessors"
|
@@ -17,6 +17,7 @@ module MimeActor
|
|
17
17
|
module Stage
|
18
18
|
extend ActiveSupport::Concern
|
19
19
|
|
20
|
+
include Rescue
|
20
21
|
include Logging
|
21
22
|
|
22
23
|
included do
|
@@ -76,37 +77,21 @@ module MimeActor
|
|
76
77
|
# @param args arguments to be passed when calling the actor
|
77
78
|
#
|
78
79
|
def cue_actor(actor, *args, action:, format:)
|
79
|
-
|
80
|
-
raise TypeError, "invalid actor, got: #{actor.inspect}" unless
|
80
|
+
dispatcher = MimeActor::Dispatcher.build(actor, *args)
|
81
|
+
raise TypeError, "invalid actor, got: #{actor.inspect}" unless dispatcher
|
81
82
|
|
82
|
-
result =
|
83
|
+
result = dispatcher.call(self)
|
83
84
|
if block_given?
|
84
85
|
yield result
|
85
86
|
else
|
86
87
|
result
|
87
88
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
rescued = false
|
95
|
-
result = catch(:abort) do
|
96
|
-
dispatch.to_callable.call(self).tap { dispatched = true }
|
97
|
-
rescue StandardError => e
|
98
|
-
rescued = respond_to?(:rescue_actor) && rescue_actor(e, action:, format:)
|
99
|
-
raise unless rescued
|
100
|
-
end
|
101
|
-
handle_actor_error(result) unless dispatched || rescued
|
102
|
-
result if dispatched
|
103
|
-
end
|
104
|
-
|
105
|
-
def handle_actor_error(actor)
|
106
|
-
error = MimeActor::ActorNotFound.new(actor)
|
107
|
-
raise error if raise_on_actor_error
|
108
|
-
|
109
|
-
logger.error { "actor error, cause: #{error.inspect}" }
|
89
|
+
rescue MimeActor::ActorNotFound => e
|
90
|
+
logger.error { "actor error, cause: #{e.inspect}" } unless raise_on_actor_error
|
91
|
+
raise e if raise_on_actor_error
|
92
|
+
rescue StandardError => e
|
93
|
+
rescued = rescue_actor(e, action:, format:)
|
94
|
+
rescued || raise
|
110
95
|
end
|
111
96
|
end
|
112
97
|
end
|
data/lib/mime_actor/validator.rb
CHANGED
@@ -32,7 +32,7 @@ module MimeActor
|
|
32
32
|
# @param rule the name of validator
|
33
33
|
def validate!(rule, *args)
|
34
34
|
validator = "validate_#{rule}"
|
35
|
-
raise NameError, "Validator not found, got: #{validator.inspect}" unless respond_to?(validator
|
35
|
+
raise NameError, "Validator not found, got: #{validator.inspect}" unless respond_to?(validator)
|
36
36
|
|
37
37
|
error = send(validator, *args)
|
38
38
|
raise error if error
|
@@ -53,6 +53,13 @@ module MimeActor
|
|
53
53
|
NameError.new("invalid actions, got: #{rejected.map(&:inspect).join(", ")}") if rejected.size.positive?
|
54
54
|
end
|
55
55
|
|
56
|
+
# Validate against `actions` rule if argument is a Enumerable. otherwise, validate against `action` rule.
|
57
|
+
#
|
58
|
+
# @param unchecked the `actions` or `action` to be validated
|
59
|
+
def validate_action_or_actions(unchecked)
|
60
|
+
unchecked.is_a?(Enumerable) ? validate_actions(unchecked) : validate_action(unchecked)
|
61
|
+
end
|
62
|
+
|
56
63
|
# Validate `format` must be a Symbol and a valid MIME type
|
57
64
|
#
|
58
65
|
# @param unchecked the `format` to be validated
|
@@ -73,6 +80,13 @@ module MimeActor
|
|
73
80
|
NameError.new("invalid formats, got: #{rejected.map(&:inspect).join(", ")}") if rejected.size.positive?
|
74
81
|
end
|
75
82
|
|
83
|
+
# Validate against `formats` rule if argument is a Enumerable. otherwise, validate against `format` rule.
|
84
|
+
#
|
85
|
+
# @param unchecked the `formats` or `format` to be validated
|
86
|
+
def validate_format_or_formats(unchecked)
|
87
|
+
unchecked.is_a?(Enumerable) ? validate_formats(unchecked) : validate_format(unchecked)
|
88
|
+
end
|
89
|
+
|
76
90
|
# Validate `klazz` must be a Class/Module or a String referencing a Class/Module
|
77
91
|
#
|
78
92
|
# @param unchecked the `klazz` to be validated
|
data/lib/mime_actor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mime_actor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.3.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Chang
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -71,6 +71,7 @@ files:
|
|
71
71
|
- codecov.yml
|
72
72
|
- lib/mime_actor.rb
|
73
73
|
- lib/mime_actor/action.rb
|
74
|
+
- lib/mime_actor/callbacks.rb
|
74
75
|
- lib/mime_actor/dispatcher.rb
|
75
76
|
- lib/mime_actor/errors.rb
|
76
77
|
- lib/mime_actor/logging.rb
|