mime_actor 0.6.4 → 0.7.1

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.
@@ -5,18 +5,24 @@
5
5
  require "mime_actor/validator"
6
6
 
7
7
  require "active_support/callbacks"
8
+ require "active_support/code_generator"
8
9
  require "active_support/concern"
9
- require "active_support/core_ext/array/wrap"
10
- require "active_support/core_ext/object/blank"
10
+ require "active_support/core_ext/module/attr_internal"
11
11
 
12
12
  module MimeActor
13
13
  # # MimeActor Callbacks
14
14
  #
15
15
  # MimeActor provides hooks during the life cycle of an act. Available callbacks are:
16
16
  #
17
- # - before_act
18
- # - around_act
19
- # - after_act
17
+ # - append_act_before
18
+ # - append_act_around
19
+ # - append_act_after
20
+ # - act_before
21
+ # - act_around
22
+ # - act_after
23
+ # - prepend_act_before
24
+ # - prepend_act_around
25
+ # - prepend_act_after
20
26
  #
21
27
  # NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
22
28
  #
@@ -27,19 +33,25 @@ module MimeActor
27
33
  include MimeActor::Validator
28
34
 
29
35
  included do
36
+ attr_internal_reader :act_action, :act_format
30
37
  define_callbacks :act, skip_after_callbacks_if_terminated: true
31
-
32
- %i[before after around].each { |kind| define_act_callbacks(kind) }
38
+ generate_act_callback_methods
33
39
  end
34
40
 
35
41
  module ClassMethods
36
- class ActionMatcher
37
- def initialize(actions)
38
- @actions = Array.wrap(actions).to_set(&:to_s)
42
+ class ActMatcher
43
+ attr_reader :actions, :formats
44
+
45
+ def initialize(actions, formats)
46
+ @actions = actions&.then { |a| Array(a).to_set(&:to_sym) }
47
+ @formats = formats&.then { |f| Array(f).to_set(&:to_sym) }
39
48
  end
40
49
 
41
50
  def match?(controller)
42
- @actions.include?(controller.action_name)
51
+ matched = true
52
+ matched &= actions.include?(controller.act_action) if !actions.nil? && controller.respond_to?(:act_action)
53
+ matched &= formats.include?(controller.act_format) if !formats.nil? && controller.respond_to?(:act_format)
54
+ matched
43
55
  end
44
56
 
45
57
  alias after match?
@@ -47,154 +59,117 @@ module MimeActor
47
59
  alias around match?
48
60
  end
49
61
 
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
62
  private
64
63
 
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
64
  def configure_callbacks(callbacks, actions, formats, block)
72
65
  options = {}
73
- options[:if] = ActionMatcher.new(actions) if actions.present?
66
+ options[:if] = ActMatcher.new(actions, formats) unless actions.nil? && formats.nil?
74
67
  callbacks.push(block) if block
75
68
 
76
- formats = Array.wrap(formats)
77
- formats << nil if formats.empty?
78
-
79
69
  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
70
+ yield callback, options
85
71
  end
86
72
  end
87
73
 
88
74
  def validate_callback_options!(action, format)
89
- validate!(:action_or_actions, action) if action.present?
90
- validate!(:format_or_formats, format) if format.present?
75
+ validate!(:action_or_actions, action) unless action.nil?
76
+ validate!(:format_or_formats, format) unless format.nil?
91
77
  end
92
78
 
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
79
+ def generate_act_callback_methods
80
+ ActiveSupport::CodeGenerator.batch(singleton_class, __FILE__, __LINE__) do |owner|
81
+ %i[before after around].each do |kind|
82
+ owner.define_cached_method(:"append_act_#{kind}", namespace: :mime_callbacks) do |batch|
83
+ batch << act_callback_kind_template(kind, append: true)
114
84
  end
85
+ owner.define_cached_method(:"prepend_act_#{kind}", namespace: :mime_callbacks) do |batch|
86
+ batch << act_callback_kind_template(kind, append: false)
87
+ end
88
+ end
89
+ end
90
+ # as: check against the defined method in owner, code only generated after #batch block is yielded
91
+ ActiveSupport::CodeGenerator.batch(singleton_class, __FILE__, __LINE__) do |owner|
92
+ %i[before after around].each do |kind|
93
+ owner.define_cached_method(:"act_#{kind}", as: :"append_act_#{kind}", namespace: :mime_callbacks)
94
+ end
95
+ end
96
+ end
115
97
 
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
98
+ def act_callback_kind_template(kind, append:)
99
+ type = append ? "append" : "prepend"
100
+ <<-RUBY
101
+ def #{type}_act_#{kind}(*callbacks, action: nil, format: nil, &block)
102
+ validate_callback_options!(action, format)
103
+ configure_callbacks(callbacks, action, format, block) do |callback, options|
104
+ set_callback(:act, :#{kind}, callback, options.merge!(prepend: #{!append}))
121
105
  end
122
- RUBY
123
- )
106
+ end
107
+ RUBY
124
108
  end
125
109
  end
126
110
 
127
111
  # Callbacks invocation sequence depends on the order of callback definition.
128
- # (except for callbacks with `format` filter).
129
112
  #
130
113
  # @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
114
+ # act_before :my_act_before_one
115
+ # act_before :my_act_before_two, action: :create
116
+ # act_before :my_act_before_three
134
117
  #
135
- # around_act :my_around_act_one
136
- # around_act :my_around_act_two, action: :create
137
- # around_act :my_around_act_three
118
+ # act_around :my_act_around_one
119
+ # act_around :my_act_around_two, action: :create
120
+ # act_around :my_act_around_three
138
121
  #
139
- # after_act :my_after_act_one
140
- # after_act :my_after_act_two, action: :create
141
- # after_act :my_after_act_three
122
+ # act_after :my_act_after_one
123
+ # act_after :my_act_after_two, action: :create
124
+ # act_after :my_act_after_three
142
125
  #
143
126
  # # 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
127
+ # # - my_act_before_one
128
+ # # - my_act_before_two
129
+ # # - my_act_before_three
130
+ # # - my_act_around_one
131
+ # # - my_act_around_two
132
+ # # - my_act_around_three
133
+ # # - my_act_after_three
134
+ # # - my_act_after_two
135
+ # # - my_act_after_one
153
136
  #
154
137
  # @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
138
+ # act_before :my_act_before_one
139
+ # act_before :my_act_before_two, action: :create
140
+ # act_before :my_act_before_three, action: :create, format: :html
141
+ # act_before :my_act_before_four
159
142
  #
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
143
+ # act_around :my_act_around_one
144
+ # act_around :my_act_around_two, action: :create, format: :html
145
+ # act_around :my_act_around_three, action: :create
146
+ # act_around :my_act_around_four
164
147
  #
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
148
+ # act_after :my_act_after_one, format: :html
149
+ # act_after :my_act_after_two
150
+ # act_after :my_act_after_three, action: :create
151
+ # act_after :my_act_after_four
169
152
  #
170
153
  # # 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
154
+ # # - my_act_before_one
155
+ # # - my_act_before_two
156
+ # # - my_act_before_four
157
+ # # - my_act_before_three
158
+ # # - my_act_around_one
159
+ # # - my_act_around_two
160
+ # # - my_act_around_three
161
+ # # - my_act_around_four
162
+ # # - my_act_after_four
163
+ # # - my_act_after_three
164
+ # # - my_act_after_two
165
+ # # - my_act_after_one
183
166
  #
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
167
+ def run_act_callbacks(action:, format:)
168
+ @_act_action = action.to_sym
169
+ @_act_format = format.to_sym
170
+
171
+ run_callbacks :act do
172
+ yield if block_given?
198
173
  end
199
174
  end
200
175
  end
@@ -6,16 +6,6 @@ require "active_support/deprecation"
6
6
 
7
7
  module MimeActor
8
8
  def self.deprecator
9
- @deprecator ||= ActiveSupport::Deprecation.new("0.7.0", "MimeActor")
9
+ @deprecator ||= ActiveSupport::Deprecation.new("0.8.0", "MimeActor")
10
10
  end
11
11
  end
12
-
13
- [
14
- [MimeActor::Rescue::ClassMethods, { rescue_actor: "use #rescue_actor instance method" }],
15
- [MimeActor::Scene::ClassMethods, { act_on_format: :respond_act_to }],
16
- [MimeActor::Stage::ClassMethods, { actor?: "no longer supported, use Object#respond_to?" }],
17
- [MimeActor::Stage::ClassMethods, { dispatch_cue: "no longer support anonymous proc with rescue" }],
18
- [MimeActor::Stage::ClassMethods, { dispatch_act: "no longer support anonymous proc with rescue" }]
19
- ].each do |klazz, *args|
20
- MimeActor.deprecator.deprecate_methods(klazz, *args)
21
- end
@@ -39,9 +39,9 @@ module MimeActor
39
39
  end
40
40
  end
41
41
 
42
- class ActionExisted < ActionError
42
+ class ActionNotImplemented < ActionError
43
43
  def generate_message
44
- "action #{action.inspect} already existed"
44
+ "action #{action.inspect} not implemented"
45
45
  end
46
46
  end
47
47
  end
@@ -2,9 +2,12 @@
2
2
 
3
3
  # :markup: markdown
4
4
 
5
+ # required by active_support/tagged_logging
6
+ require "active_support/version"
7
+ require "active_support/isolated_execution_state" if ActiveSupport::VERSION::MAJOR >= 7
8
+
5
9
  require "active_support/concern"
6
10
  require "active_support/configurable"
7
- require "active_support/isolated_execution_state" # required by active_support/logger
8
11
  require "active_support/logger"
9
12
  require "active_support/tagged_logging"
10
13
 
@@ -18,7 +21,14 @@ module MimeActor
18
21
  include ActiveSupport::Configurable
19
22
 
20
23
  included do
21
- config_accessor :logger, default: ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new($stdout))
24
+ default_logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new($stdout))
25
+ if ActiveSupport::VERSION::MAJOR >= 7
26
+ config_accessor :logger, default: default_logger
27
+ else
28
+ config_accessor :logger do
29
+ default_logger
30
+ end
31
+ end
22
32
  end
23
33
 
24
34
  private
@@ -5,7 +5,7 @@
5
5
  module MimeActor
6
6
  class Railtie < Rails::Railtie
7
7
  initializer "mime_actor.deprecator", before: :load_environment_config do |app|
8
- app.deprecators[:mime_actor] = MimeActor.deprecator
8
+ app.deprecators[:mime_actor] = MimeActor.deprecator if Rails::VERSION::MAJOR >= 7
9
9
  end
10
10
  end
11
11
  end
@@ -6,9 +6,7 @@ require "mime_actor/dispatcher"
6
6
  require "mime_actor/validator"
7
7
 
8
8
  require "active_support/concern"
9
- require "active_support/core_ext/array/wrap"
10
9
  require "active_support/core_ext/module/attribute_accessors"
11
- require "active_support/core_ext/object/blank"
12
10
  require "active_support/core_ext/string/inflections"
13
11
 
14
12
  module MimeActor
@@ -47,13 +45,13 @@ module MimeActor
47
45
  #
48
46
  def rescue_act_from(*klazzes, action: nil, format: nil, with: nil, &block)
49
47
  raise ArgumentError, "error filter is required" if klazzes.empty?
50
- raise ArgumentError, "provide either with: or a block" unless with.present? ^ block_given?
48
+ raise ArgumentError, "provide either with: or a block" unless !with.nil? ^ block_given?
51
49
 
52
- validate!(:callable, with) if with.present?
50
+ validate!(:callable, with) unless with.nil?
53
51
  with = block if block_given?
54
52
 
55
- validate!(:action_or_actions, action) if action.present?
56
- validate!(:format_or_formats, format) if format.present?
53
+ validate!(:action_or_actions, action) unless action.nil?
54
+ validate!(:format_or_formats, format) unless format.nil?
57
55
 
58
56
  klazzes.each do |klazz|
59
57
  validate!(:klazz, klazz)
@@ -63,72 +61,6 @@ module MimeActor
63
61
  actor_rescuers << [error, format, action, with]
64
62
  end
65
63
  end
66
-
67
- # Resolve the error provided with the registered handlers.
68
- #
69
- # The handled error will be returned to indicate successful handling.
70
- #
71
- # @param error the error instance to rescue
72
- # @param action the `action` filter
73
- # @param format the `format` filter
74
- # @param context the context to evaluate for rescue handler
75
- # @param visited the errors to skip after no rescue handler matched the filter
76
- #
77
- def rescue_actor(error, action: nil, format: nil, context: self, visited: [])
78
- return if visited.include?(error)
79
-
80
- visited << error
81
- if (rescuer = dispatch_rescuer(error, format:, action:, context:))
82
- rescuer.call(error, format, action)
83
- error
84
- elsif error&.cause
85
- rescue_actor(error.cause, format:, action:, context:, visited:)
86
- end
87
- end
88
-
89
- private
90
-
91
- def dispatch_rescuer(error, format:, action:, context:)
92
- case rescuer = find_rescuer(error, format:, action:)
93
- when Symbol
94
- rescuer_method = context.method(rescuer)
95
- lambda do |*args|
96
- passable_args = rescuer_method.arity.negative? ? args : args.take(rescuer_method.arity)
97
- rescuer_method.call(*passable_args)
98
- end
99
- when Proc
100
- lambda do |*args|
101
- passable_args = rescuer.arity.negative? ? args : args.take(rescuer.arity)
102
- context.instance_exec(*passable_args, &rescuer)
103
- end
104
- end
105
- end
106
-
107
- def find_rescuer(error, format:, action:)
108
- return unless error
109
-
110
- *_, rescuer = actor_rescuers.reverse_each.detect do |rescuee, format_filter, action_filter|
111
- next if action_filter.present? && !Array.wrap(action_filter).include?(action)
112
- next if format_filter.present? && !Array.wrap(format_filter).include?(format)
113
- next unless (klazz = constantize_rescuee(rescuee))
114
-
115
- error.is_a?(klazz)
116
- end
117
- rescuer
118
- end
119
-
120
- def constantize_rescuee(class_or_name)
121
- case class_or_name
122
- when String, Symbol
123
- begin
124
- const_get(class_or_name)
125
- rescue NameError
126
- class_or_name.safe_constantize
127
- end
128
- else
129
- class_or_name
130
- end
131
- end
132
64
  end
133
65
 
134
66
  # Resolve the error provided with the registered handlers.
@@ -159,8 +91,8 @@ module MimeActor
159
91
  return unless error
160
92
 
161
93
  *_, rescuer = actor_rescuers.reverse_each.detect do |rescuee, format_filter, action_filter|
162
- next if action_filter.present? && !Array.wrap(action_filter).include?(action)
163
- next if format_filter.present? && !Array.wrap(format_filter).include?(format)
94
+ next unless action_filter.nil? || Array(action_filter).include?(action)
95
+ next unless format_filter.nil? || Array(format_filter).include?(format)
164
96
  next unless (klazz = constantize_rescuee(rescuee))
165
97
 
166
98
  error.is_a?(klazz)