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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +197 -0
- data/COMPARE.md +40 -32
- data/README.md +130 -25
- data/lib/mime_actor/action.rb +23 -15
- data/lib/mime_actor/callbacks.rb +101 -126
- data/lib/mime_actor/deprecator.rb +1 -11
- data/lib/mime_actor/errors.rb +2 -2
- data/lib/mime_actor/logging.rb +12 -2
- data/lib/mime_actor/railtie.rb +1 -1
- data/lib/mime_actor/rescue.rb +6 -74
- data/lib/mime_actor/scene.rb +77 -68
- data/lib/mime_actor/stage.rb +3 -47
- data/lib/mime_actor/validator.rb +4 -0
- data/lib/mime_actor/version.rb +2 -2
- metadata +13 -26
data/lib/mime_actor/scene.rb
CHANGED
@@ -5,36 +5,29 @@
|
|
5
5
|
require "mime_actor/errors"
|
6
6
|
require "mime_actor/validator"
|
7
7
|
|
8
|
+
require "active_support/code_generator"
|
8
9
|
require "active_support/concern"
|
9
|
-
require "active_support/core_ext/array/wrap"
|
10
10
|
require "active_support/core_ext/module/attribute_accessors"
|
11
|
-
require "active_support/core_ext/object/blank"
|
12
11
|
|
13
12
|
module MimeActor
|
14
13
|
# # MimeActor Scene
|
15
14
|
#
|
16
15
|
# Scene provides configuration for `action` + `format` definitions
|
17
16
|
#
|
18
|
-
# @example register a `html` format on action `
|
19
|
-
#
|
17
|
+
# @example register a `html` format on action `create`
|
18
|
+
# act_on_action :create, format: :html
|
20
19
|
#
|
21
|
-
# # this method should be defined in the class
|
22
|
-
# def index_html; end
|
23
20
|
# @example register `html`, `json` formats on actions `index`, `show`
|
24
|
-
#
|
21
|
+
# act_on_action :index, :show, format: [:html, :json]
|
25
22
|
#
|
26
|
-
# # these methods should be defined in the class
|
27
|
-
# def index_html; end
|
28
|
-
# def index_json; end
|
29
|
-
# def show_html; end
|
30
|
-
# def show_json; end
|
31
23
|
# @example register a `html` format on action `index` with respond handler method
|
32
|
-
#
|
24
|
+
# act_on_action :index, format: :html, with: :render_html
|
33
25
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
26
|
+
# @example register a `html` format on action `index` with respond handler Proc
|
27
|
+
# act_on_action :index, format: :html, with: -> { render html: "<h1>my header</h1>" }
|
28
|
+
#
|
29
|
+
# @example register a `html` format on action `index` with respond handler block
|
30
|
+
# act_on_action :html, on: :index do
|
38
31
|
# render :index
|
39
32
|
# end
|
40
33
|
#
|
@@ -52,78 +45,94 @@ module MimeActor
|
|
52
45
|
module ClassMethods
|
53
46
|
# Register `action` + `format` definitions.
|
54
47
|
#
|
55
|
-
# @param
|
56
|
-
# @param
|
57
|
-
# @param with the respond handler
|
58
|
-
# @param block the `block` to
|
48
|
+
# @param action a collection of `action`
|
49
|
+
# @param format a single `format` or a collection of `format`
|
50
|
+
# @param with the respond handler for the given `action` + `format`
|
51
|
+
# @param block the `block` to be yieled for the given `action` + `format`
|
59
52
|
#
|
60
|
-
# @example register a `html` format on action `
|
61
|
-
#
|
53
|
+
# @example register a `html` format on action `create`
|
54
|
+
# act_on_action :create, format: :html
|
62
55
|
#
|
63
|
-
# #
|
64
|
-
# def
|
56
|
+
# # an action method will be defined in the class
|
57
|
+
# def indexl; end
|
65
58
|
# @example register `html`, `json` formats on actions `index`, `show`
|
66
|
-
#
|
59
|
+
# act_on_action :index, :show, format: [:html, :json]
|
67
60
|
#
|
68
|
-
# # these methods
|
69
|
-
# def
|
70
|
-
# def
|
71
|
-
# def show_html; end
|
72
|
-
# def show_json; end
|
61
|
+
# # these action methods will be defined in the class
|
62
|
+
# def index; end
|
63
|
+
# def show; end
|
73
64
|
# @example register a `html` format on action `index` with respond handler method
|
74
|
-
#
|
65
|
+
# act_on_action :index, format: :html, with: :render_html
|
75
66
|
#
|
76
|
-
# #
|
67
|
+
# # an action method will be defined in the class
|
68
|
+
# # the handler method will be called by the action method.
|
69
|
+
# def index; end
|
70
|
+
# # the given method should be defined in the class
|
77
71
|
# def render_html; end
|
78
|
-
# @example register a `html` format on action `index` with respond handler
|
79
|
-
#
|
72
|
+
# @example register a `html` format on action `index` with respond handler Proc
|
73
|
+
# act_on_action :index, format: :html, with: -> { render html: "<h1>my header</h1>" }
|
74
|
+
#
|
75
|
+
# # an action method will be defined in the class,
|
76
|
+
# # the handler Proc will be called by the action method.
|
77
|
+
# def index; end
|
78
|
+
# @example register a `html` format on action `index` with respond handler block
|
79
|
+
# act_on_action :html, on: :index do
|
80
80
|
# render :index
|
81
81
|
# end
|
82
82
|
#
|
83
|
-
#
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
83
|
+
# # an action method will be defined in the class
|
84
|
+
# def index; end
|
85
|
+
#
|
86
|
+
# For each unique `action` being registered, a corresponding `action` method will be defined.
|
87
|
+
def act_on_action(*actions, format:, with: nil, &block)
|
88
|
+
raise ArgumentError, "format is required" if format.nil?
|
89
|
+
raise ArgumentError, "provide either with: or a block" if !with.nil? && block_given?
|
90
|
+
|
91
|
+
validate!(:actions, actions)
|
92
|
+
validate!(:format_or_formats, format)
|
93
|
+
validate!(:callable, with) unless with.nil?
|
90
94
|
with = block if block_given?
|
91
95
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
formats.each { |format| compose_scene(action, format, with) }
|
96
|
+
actions.each do |action|
|
97
|
+
acting_scenes[action] ||= {}
|
98
|
+
Array(format).each do |action_format|
|
99
|
+
acting_scenes[action][action_format] = with
|
100
|
+
end
|
98
101
|
end
|
99
|
-
end
|
100
102
|
|
101
|
-
|
102
|
-
|
103
|
+
generate_action_methods(actions)
|
104
|
+
end
|
103
105
|
|
104
106
|
private
|
105
107
|
|
106
|
-
def
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
acting_scenes[action] ||= {}
|
111
|
-
acting_scenes[action][format] = actor
|
108
|
+
def generated_action_methods
|
109
|
+
@generated_action_methods ||= Module.new.tap { |mod| prepend mod }
|
110
|
+
end
|
112
111
|
|
113
|
-
|
112
|
+
def generate_action_methods(actions)
|
113
|
+
ActiveSupport::CodeGenerator.batch(generated_action_methods, __FILE__, __LINE__) do |owner|
|
114
|
+
actions.each do |action|
|
115
|
+
owner.define_cached_method(action, namespace: :mime_scene) do |batch|
|
116
|
+
batch << action_method_template(action)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
114
120
|
end
|
115
121
|
|
116
|
-
def
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
122
|
+
def action_method_template(action)
|
123
|
+
<<-RUBY
|
124
|
+
def #{action}
|
125
|
+
if respond_to?(:start_scene)
|
126
|
+
start_scene do
|
127
|
+
raise #{MimeActor::ActionNotImplemented}, :#{action} unless defined?(super)
|
128
|
+
super
|
129
|
+
end
|
130
|
+
else
|
131
|
+
raise #{MimeActor::ActionNotImplemented}, :#{action} unless defined?(super)
|
132
|
+
super
|
124
133
|
end
|
125
|
-
|
126
|
-
|
134
|
+
end
|
135
|
+
RUBY
|
127
136
|
end
|
128
137
|
end
|
129
138
|
end
|
data/lib/mime_actor/stage.rb
CHANGED
@@ -26,50 +26,6 @@ module MimeActor
|
|
26
26
|
mattr_accessor :raise_on_actor_error, instance_writer: false, default: false
|
27
27
|
end
|
28
28
|
|
29
|
-
module ClassMethods
|
30
|
-
# Determine if the `actor_name` belongs to a public instance method excluding methods inherited from ancestors
|
31
|
-
#
|
32
|
-
# @param actor_name
|
33
|
-
#
|
34
|
-
def actor?(actor_name)
|
35
|
-
# exclude public methods from ancestors
|
36
|
-
found = public_instance_methods(false).include?(actor_name.to_sym)
|
37
|
-
# exclude private methods from ancestors
|
38
|
-
if !found && private_instance_methods(false).include?(actor_name.to_sym)
|
39
|
-
logger.debug { "actor must be public method, #{actor_name} is private method" }
|
40
|
-
end
|
41
|
-
found
|
42
|
-
end
|
43
|
-
|
44
|
-
# Wraps the given `block` with a `lambda`, rescue any error raised from the `block`.
|
45
|
-
# Otherwise, error will be re-raised.
|
46
|
-
#
|
47
|
-
# @param action the `action` to be passed on to `rescue_actor`
|
48
|
-
# @param format the `format` to be passed on to `rescue_actor`
|
49
|
-
# @param context the context for the block evaluation
|
50
|
-
# @param block the `block` to be evaluated
|
51
|
-
#
|
52
|
-
# @example Dispatch a cue that prints out a text
|
53
|
-
# dispatch = self.class.dispatch_act(action: :create, format: :json, context: self) do
|
54
|
-
# puts "completed the dispatch"
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# dispatch.call == "completed the dispatch" # true
|
58
|
-
#
|
59
|
-
def dispatch_act(action: nil, format: nil, context: self, &block)
|
60
|
-
raise ArgumentError, "block must be provided" unless block_given?
|
61
|
-
|
62
|
-
lambda do
|
63
|
-
context.instance_exec(&block)
|
64
|
-
rescue StandardError => e
|
65
|
-
(respond_to?(:rescue_actor) && rescue_actor(e, action:, format:, context:)) || raise
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# TODO: remove on next breaking change release
|
70
|
-
alias dispatch_cue dispatch_act
|
71
|
-
end
|
72
|
-
|
73
29
|
# Calls the `actor` and passing arguments to it.
|
74
30
|
# If a block is given, the result from the `actor` method will be yieled to the block.
|
75
31
|
#
|
@@ -78,13 +34,13 @@ module MimeActor
|
|
78
34
|
# @param actor either a method name or a Proc to evaluate
|
79
35
|
# @param args arguments to be passed when calling the actor
|
80
36
|
#
|
81
|
-
def cue_actor(actor, *args, format:)
|
37
|
+
def cue_actor(actor, *args, action:, format:)
|
82
38
|
dispatcher = MimeActor::Dispatcher.build(actor, *args)
|
83
39
|
raise TypeError, "invalid actor, got: #{actor.inspect}" unless dispatcher
|
84
40
|
|
85
41
|
self.class.validate!(:format, format)
|
86
42
|
|
87
|
-
run_act_callbacks(format) do
|
43
|
+
run_act_callbacks(action:, format:) do
|
88
44
|
result = dispatcher.call(self)
|
89
45
|
block_given? ? yield(result) : result
|
90
46
|
end
|
@@ -92,7 +48,7 @@ module MimeActor
|
|
92
48
|
logger.error { "actor error, cause: #{e.inspect}" } unless raise_on_actor_error
|
93
49
|
raise e if raise_on_actor_error
|
94
50
|
rescue StandardError => e
|
95
|
-
rescued = rescue_actor(e, action
|
51
|
+
rescued = rescue_actor(e, action:, format:)
|
96
52
|
rescued || raise
|
97
53
|
end
|
98
54
|
end
|
data/lib/mime_actor/validator.rb
CHANGED
@@ -49,6 +49,8 @@ module MimeActor
|
|
49
49
|
#
|
50
50
|
# @param unchecked the `actions` to be validated
|
51
51
|
def validate_actions(unchecked)
|
52
|
+
return TypeError.new("actions must not be empty") if unchecked.empty?
|
53
|
+
|
52
54
|
rejected = unchecked.reject { |action| action.is_a?(Symbol) }
|
53
55
|
NameError.new("invalid actions, got: #{rejected.map(&:inspect).join(", ")}") if rejected.size.positive?
|
54
56
|
end
|
@@ -73,6 +75,8 @@ module MimeActor
|
|
73
75
|
#
|
74
76
|
# @param unchecked the `formats` to be validated
|
75
77
|
def validate_formats(unchecked)
|
78
|
+
return TypeError.new("formats must not be empty") if unchecked.empty?
|
79
|
+
|
76
80
|
unfiltered = unchecked.to_set
|
77
81
|
filtered = unfiltered & scene_formats
|
78
82
|
rejected = unfiltered - filtered
|
data/lib/mime_actor/version.rb
CHANGED
metadata
CHANGED
@@ -1,57 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mime_actor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
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-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '7.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '7.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '7.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '11.0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '11.0'
|
40
|
+
version: '7.0'
|
55
41
|
description: ''
|
56
42
|
email:
|
57
43
|
- ryancyq@gmail.com
|
@@ -59,6 +45,7 @@ executables: []
|
|
59
45
|
extensions: []
|
60
46
|
extra_rdoc_files: []
|
61
47
|
files:
|
48
|
+
- CHANGELOG.md
|
62
49
|
- COMPARE.md
|
63
50
|
- LICENSE
|
64
51
|
- README.md
|
@@ -91,9 +78,9 @@ require_paths:
|
|
91
78
|
- lib
|
92
79
|
required_ruby_version: !ruby/object:Gem::Requirement
|
93
80
|
requirements:
|
94
|
-
- - "
|
81
|
+
- - "~>"
|
95
82
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.1
|
83
|
+
version: '3.1'
|
97
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
85
|
requirements:
|
99
86
|
- - ">="
|