mime_actor 0.5.3 → 0.6.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/.rubocop.yml +4 -0
- data/.yardopts +2 -0
- data/COMPARE.md +4 -4
- data/README.md +4 -4
- data/lib/mime_actor/action.rb +17 -4
- data/lib/mime_actor/logging.rb +1 -1
- data/lib/mime_actor/rescue.rb +32 -30
- data/lib/mime_actor/scene.rb +49 -33
- data/lib/mime_actor/stage.rb +26 -10
- data/lib/mime_actor/validator.rb +36 -22
- 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: 031455cd4203f02b1760129516e1a8722af2f84d7580cf1799f886d98262cdea
|
4
|
+
data.tar.gz: 78b2841148310600b408fd3d2932741ab61280f24afb28f0b251e62bcba91419
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2852a58bb4dc628d293e6d5974b452144496be454a2a594aec90baaffcf5fbbcdd096745778853f36cc5e8ef4eb577340175bd76533ba2be1852799ddf5cc2a6
|
7
|
+
data.tar.gz: f548c1d8fe2c32a2aba34c4b9189e3e02272fdcfdc850d8b88e6cb6eea54514a1c95cc8ede181656f5ba0e92111f2566db1cbc98b647dd77f0922cd2ff1357be
|
data/.rubocop.yml
CHANGED
data/.yardopts
ADDED
data/COMPARE.md
CHANGED
@@ -27,7 +27,7 @@ class EventsController < ActionController::Base
|
|
27
27
|
before_action only: :index { @events = Event.all }
|
28
28
|
|
29
29
|
# dynamically defines the action method according to on: argument
|
30
|
-
|
30
|
+
act_on_format :html, :json, on: :index
|
31
31
|
|
32
32
|
def index_html
|
33
33
|
@event_categories = EventCategory.all
|
@@ -92,13 +92,13 @@ class EventsController < ActionController::Base
|
|
92
92
|
# AbstractController::Callbacks here to load model with params
|
93
93
|
before_action only: [:show, :update] { @event = Event.find(params.require(:event_id)) }
|
94
94
|
|
95
|
-
|
95
|
+
act_on_format :html, :json, on: [:show, :update]
|
96
96
|
|
97
|
-
|
97
|
+
rescue_act_from ActiveRecord::RecordNotFound, format: :json do |ex|
|
98
98
|
render status: :bad_request, json: { error: ex.message }
|
99
99
|
end
|
100
100
|
|
101
|
-
|
101
|
+
rescue_act_from ActiveRecord::RecordNotFound, format: :html, action: :show do |ex|
|
102
102
|
redirect_to events_path
|
103
103
|
end
|
104
104
|
|
data/README.md
CHANGED
@@ -16,14 +16,14 @@ class EventsController < ActionController::Base
|
|
16
16
|
before_action only: :index { @events = Event.all }
|
17
17
|
before_action only: [:show, :update] { @event = Event.find(params.require(:event_id)) }
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
act_on_format :html, :json, on: :index
|
20
|
+
act_on_format :html, :json, on: [:show, :update]
|
21
21
|
|
22
|
-
|
22
|
+
rescue_act_from ActiveRecord::RecordNotFound, format: :json do |ex|
|
23
23
|
render status: :bad_request, json: { error: "Resouce not found" }
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
rescue_act_from ActiveRecord::RecordNotFound, format: :html, action: :show do |ex|
|
27
27
|
redirect_to events_path
|
28
28
|
end
|
29
29
|
|
data/lib/mime_actor/action.rb
CHANGED
@@ -12,9 +12,9 @@ require "action_controller/metal/mime_responds"
|
|
12
12
|
module MimeActor
|
13
13
|
# # MimeActor Action
|
14
14
|
#
|
15
|
-
# Action is the recommended Module to be included in ActionController
|
15
|
+
# `Action` is the recommended `Module` to be included in the `ActionController`.
|
16
16
|
#
|
17
|
-
# Provides intuitive way of action rendering for a specific MIME type with rescue handlers.
|
17
|
+
# Provides intuitive way of `action` rendering for a specific MIME type with rescue handlers.
|
18
18
|
#
|
19
19
|
module Action
|
20
20
|
extend ActiveSupport::Concern
|
@@ -27,8 +27,21 @@ module MimeActor
|
|
27
27
|
include Rescue
|
28
28
|
include Logging
|
29
29
|
|
30
|
-
|
31
|
-
#
|
30
|
+
# The core logic where rendering logics are collected as `Proc` and passed over to `ActionController::MimeResponds`
|
31
|
+
#
|
32
|
+
# @param action the `action` of the controller
|
33
|
+
#
|
34
|
+
# @example process `create` action
|
35
|
+
# start_scene(:create)
|
36
|
+
#
|
37
|
+
# # it is equivalent to the following if `create` action is configured with `html` and `json` formats
|
38
|
+
# def create
|
39
|
+
# respond_to |format|
|
40
|
+
# format.html { public_send(:create_html) }
|
41
|
+
# format.json { public_send(:create_json) }
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
32
45
|
def start_scene(action)
|
33
46
|
action = action&.to_sym
|
34
47
|
formats = acting_scenes.fetch(action, Set.new)
|
data/lib/mime_actor/logging.rb
CHANGED
data/lib/mime_actor/rescue.rb
CHANGED
@@ -13,7 +13,10 @@ require "active_support/core_ext/string/inflections"
|
|
13
13
|
module MimeActor
|
14
14
|
# # MimeActor Rescue
|
15
15
|
#
|
16
|
-
# Simillar to ActionController::Rescue but with additional filtering logic on
|
16
|
+
# Simillar to `ActionController::Rescue` but with additional filtering logic on `action`/`format`.
|
17
|
+
#
|
18
|
+
# @example Rescue RuntimeError when raised for any action with `json` format
|
19
|
+
# rescue_act_from RuntimeError, format: :json, with: :handle_json_error
|
17
20
|
#
|
18
21
|
module Rescue
|
19
22
|
extend ActiveSupport::Concern
|
@@ -25,57 +28,56 @@ module MimeActor
|
|
25
28
|
mattr_accessor :actor_rescuers, instance_writer: false, default: []
|
26
29
|
end
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
#
|
31
|
+
class_methods do
|
32
|
+
# Registers a rescue handler for the given error classes with `action`/`format` filter
|
33
|
+
#
|
34
|
+
# @param klazzes the error classes to rescue
|
35
|
+
# @param action the `action` filter
|
36
|
+
# @param format the `format` filter
|
37
|
+
# @param with the rescue hanlder when `block` is not provided
|
38
|
+
# @param block the `block` to evaluate when `with` is not provided
|
31
39
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# end
|
40
|
+
# @example Rescue StandardError when raised for any action with `html` format
|
41
|
+
# rescue_act_from StandardError, format: :html, with: :handle_html_error
|
35
42
|
#
|
36
|
-
#
|
43
|
+
# @example Rescue StandardError when raised for `show` action with `json` format
|
44
|
+
# rescue_act_from StandardError, format: :json, action: :show do |ex|
|
45
|
+
# render status: :bad_request, json: { error: ex.message }
|
46
|
+
# end
|
37
47
|
#
|
38
|
-
def
|
48
|
+
def rescue_act_from(*klazzes, action: nil, format: nil, with: nil, &block)
|
39
49
|
raise ArgumentError, "error filter is required" if klazzes.empty?
|
40
50
|
|
41
51
|
validate!(:with, with, block)
|
42
52
|
with = block if block_given?
|
43
53
|
|
44
54
|
if action.present?
|
45
|
-
|
46
|
-
validate!(:actions, action)
|
47
|
-
else
|
48
|
-
validate!(:action, action)
|
49
|
-
end
|
55
|
+
action.is_a?(Enumerable) ? validate!(:actions, action) : validate!(:action, action)
|
50
56
|
end
|
51
57
|
|
52
58
|
if format.present?
|
53
|
-
|
54
|
-
validate!(:formats, format)
|
55
|
-
else
|
56
|
-
validate!(:format, format)
|
57
|
-
end
|
59
|
+
format.is_a?(Enumerable) ? validate!(:formats, format) : validate!(:format, format)
|
58
60
|
end
|
59
61
|
|
60
62
|
klazzes.each do |klazz|
|
61
|
-
|
62
|
-
|
63
|
-
klazz.name
|
64
|
-
when String
|
65
|
-
klazz
|
66
|
-
else
|
67
|
-
message = "#{klazz.inspect} must be a Class/Module or a String referencing a Class/Module"
|
68
|
-
raise ArgumentError, message
|
69
|
-
end
|
63
|
+
validate!(:klazz, klazz)
|
64
|
+
error = klazz.is_a?(Module) ? klazz.name : klazz
|
70
65
|
|
71
66
|
# append at the end because strategies are read in reverse.
|
72
67
|
actor_rescuers << [error, format, action, with]
|
73
68
|
end
|
74
69
|
end
|
75
70
|
|
76
|
-
##
|
77
71
|
# Resolve the error provided with the registered handlers.
|
78
|
-
#
|
72
|
+
#
|
73
|
+
# The handled error will be returned to indicate successful handling.
|
74
|
+
#
|
75
|
+
# @param error the error instance to rescue
|
76
|
+
# @param action the `action` filter
|
77
|
+
# @param format the `format` filter
|
78
|
+
# @param context the context to evaluate for rescue handler
|
79
|
+
# @param visited the errors to skip after no rescue handler matched the filter
|
80
|
+
#
|
79
81
|
def rescue_actor(error, action: nil, format: nil, context: self, visited: [])
|
80
82
|
return if visited.include?(error)
|
81
83
|
|
data/lib/mime_actor/scene.rb
CHANGED
@@ -13,12 +13,14 @@ require "active_support/core_ext/module/attribute_accessors"
|
|
13
13
|
module MimeActor
|
14
14
|
# # MimeActor Scene
|
15
15
|
#
|
16
|
-
# Scene provides configuration for
|
16
|
+
# Scene provides configuration for `action` + `format` definitions
|
17
17
|
#
|
18
|
-
#
|
19
|
-
#
|
18
|
+
# @example register a `html` format on action `index`
|
19
|
+
# act_on_format :html, on: :index
|
20
|
+
# @example register `html`, `json` formats on actions `index`, `show`
|
21
|
+
# act_on_format :html, :json , on: [:index, :show]
|
20
22
|
#
|
21
|
-
# NOTE: Calling the same action
|
23
|
+
# NOTE: Calling the same `action`/`format` multiple times will overwrite previous `action` + `format` definitions.
|
22
24
|
#
|
23
25
|
module Scene
|
24
26
|
extend ActiveSupport::Concern
|
@@ -29,46 +31,60 @@ module MimeActor
|
|
29
31
|
mattr_accessor :acting_scenes, instance_writer: false, default: {}
|
30
32
|
end
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
# Register Action + Format definitions.
|
34
|
+
class_methods do
|
35
|
+
# Register `action` + `format` definitions.
|
35
36
|
#
|
36
|
-
#
|
37
|
-
|
37
|
+
# @param options [Array]
|
38
|
+
# @option options [Array] klazzes the collection of `format`
|
39
|
+
# @option options [Hash] on the collection of `action`
|
40
|
+
#
|
41
|
+
# @example register a `html` format on action `index`
|
42
|
+
# act_on_format :html, on: :index
|
43
|
+
# @example register `html`, `json` formats on actions `index`, `show`
|
44
|
+
# act_on_format :html, :json , on: [:index, :show]
|
45
|
+
#
|
46
|
+
# For each unique `action` being registered, it will have a corresponding `action` method being defined.
|
47
|
+
def act_on_format(*options)
|
38
48
|
config = options.extract_options!
|
39
49
|
validate!(:formats, options)
|
40
50
|
|
41
|
-
actions = config[:on]
|
42
|
-
|
43
|
-
raise ArgumentError, "action is required"
|
44
|
-
elsif actions.is_a?(Enumerable)
|
51
|
+
case actions = config[:on]
|
52
|
+
when Enumerable
|
45
53
|
validate!(:actions, actions)
|
46
|
-
|
54
|
+
when Symbol, String
|
47
55
|
validate!(:action, actions)
|
56
|
+
else
|
57
|
+
raise ArgumentError, "action is required"
|
48
58
|
end
|
49
59
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
60
|
+
Array.wrap(actions).each do |action|
|
61
|
+
options.each { |format| compose_scene(action, format) }
|
62
|
+
end
|
63
|
+
end
|
54
64
|
|
55
|
-
|
56
|
-
acting_scenes[action] |= [format]
|
65
|
+
private
|
57
66
|
|
58
|
-
|
67
|
+
def compose_scene(action, format)
|
68
|
+
action_defined = (instance_methods + private_instance_methods).include?(action.to_sym)
|
69
|
+
raise MimeActor::ActionExisted, action if !acting_scenes.key?(action) && action_defined
|
59
70
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
71
|
-
|
71
|
+
acting_scenes[action] ||= Set.new
|
72
|
+
acting_scenes[action] |= [format]
|
73
|
+
|
74
|
+
define_scene(action) unless action_defined
|
75
|
+
end
|
76
|
+
|
77
|
+
def define_scene(action)
|
78
|
+
class_eval(
|
79
|
+
# def index
|
80
|
+
# self.respond_to?(:start_scene) && self.start_scene(:index)
|
81
|
+
# end
|
82
|
+
<<-RUBY, __FILE__, __LINE__ + 1
|
83
|
+
def #{action}
|
84
|
+
self.respond_to?(:start_scene) && self.start_scene(:#{action})
|
85
|
+
end
|
86
|
+
RUBY
|
87
|
+
)
|
72
88
|
end
|
73
89
|
end
|
74
90
|
end
|
data/lib/mime_actor/stage.rb
CHANGED
@@ -11,7 +11,7 @@ require "active_support/core_ext/module/attribute_accessors"
|
|
11
11
|
module MimeActor
|
12
12
|
# # MimeActor Stage
|
13
13
|
#
|
14
|
-
# Stage provides
|
14
|
+
# Stage provides helper methods for actor lookup and invocation.
|
15
15
|
#
|
16
16
|
module Stage
|
17
17
|
extend ActiveSupport::Concern
|
@@ -22,9 +22,11 @@ module MimeActor
|
|
22
22
|
mattr_accessor :raise_on_missing_actor, instance_writer: false, default: false
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
#
|
25
|
+
class_methods do
|
26
|
+
# Determine if the `actor_name` belongs to a public instance method excluding methods inherited from ancestors
|
27
|
+
#
|
28
|
+
# @param actor_name
|
29
|
+
#
|
28
30
|
def actor?(actor_name)
|
29
31
|
# exclude public methods from ancestors
|
30
32
|
found = public_instance_methods(false).include?(actor_name.to_sym)
|
@@ -35,8 +37,21 @@ module MimeActor
|
|
35
37
|
found
|
36
38
|
end
|
37
39
|
|
38
|
-
|
39
|
-
#
|
40
|
+
# Wraps the given `block` with a `lambda`, rescue any error raised from the `block`.
|
41
|
+
# Otherwise, error will be re-raised.
|
42
|
+
#
|
43
|
+
# @param action the `action` to be passed on to `rescue_actor`
|
44
|
+
# @param format the `format` to be passed on to `rescue_actor`
|
45
|
+
# @param context the context for the block evaluation
|
46
|
+
# @param block the `block` to be evaluated
|
47
|
+
#
|
48
|
+
# @example Dispatch a cue that prints out a text
|
49
|
+
# dispatch = self.class.dispatch_cue(action: :create, format: :json, context: self) do
|
50
|
+
# puts "completed the dispatch"
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# dispatch.call == "completed the dispatch" # true
|
54
|
+
#
|
40
55
|
def dispatch_cue(action: nil, format: nil, context: self, &block)
|
41
56
|
raise ArgumentError, "block must be provided" unless block_given?
|
42
57
|
|
@@ -48,10 +63,11 @@ module MimeActor
|
|
48
63
|
end
|
49
64
|
end
|
50
65
|
|
51
|
-
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
66
|
+
# Calls the `actor` method if defined, supports passing arguments to the `actor` method.
|
67
|
+
#
|
68
|
+
# If a block is given, the result from the `actor` method will be yieled to the block.
|
69
|
+
#
|
70
|
+
# @param actor_name
|
55
71
|
def cue_actor(actor_name, *args)
|
56
72
|
unless self.class.actor?(actor_name)
|
57
73
|
raise MimeActor::ActorNotFound, actor_name if raise_on_missing_actor
|
data/lib/mime_actor/validator.rb
CHANGED
@@ -9,14 +9,14 @@ require "action_dispatch/http/mime_type"
|
|
9
9
|
module MimeActor
|
10
10
|
# # MimeActor Validator
|
11
11
|
#
|
12
|
-
# Validator provides validation rules for action
|
12
|
+
# Validator provides validation rules for `action`, `format`, and `with` handlers by default.
|
13
13
|
#
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# @example Raise error when rule is violated
|
15
|
+
# validate!(:action, action_param)
|
16
16
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
17
|
+
# @example Return the error when rule is violated
|
18
|
+
# ex = validate_action(action_param)
|
19
|
+
# raise ex if error
|
20
20
|
#
|
21
21
|
module Validator
|
22
22
|
extend ActiveSupport::Concern
|
@@ -25,9 +25,10 @@ module MimeActor
|
|
25
25
|
mattr_accessor :scene_formats, instance_writer: false, default: Mime::SET.symbols.to_set
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
#
|
28
|
+
class_methods do
|
29
|
+
# Raise the error returned by validator if any.
|
30
|
+
#
|
31
|
+
# @param rule the name of validator
|
31
32
|
def validate!(rule, *args)
|
32
33
|
validator = "validate_#{rule}"
|
33
34
|
raise NameError, "Validator not found, got: #{validator}" unless respond_to?(validator, true)
|
@@ -36,29 +37,33 @@ module MimeActor
|
|
36
37
|
raise error if error
|
37
38
|
end
|
38
39
|
|
39
|
-
|
40
|
-
#
|
40
|
+
# Validate `action` must be a Symbol
|
41
|
+
#
|
42
|
+
# @param unchecked the `action` to be validated
|
41
43
|
def validate_action(unchecked)
|
42
44
|
ArgumentError.new("action must be a Symbol") unless unchecked.is_a?(Symbol)
|
43
45
|
end
|
44
46
|
|
45
|
-
|
46
|
-
#
|
47
|
+
# Validate `actions` must be a collection of Symbol
|
48
|
+
#
|
49
|
+
# @param unchecked the `actions` to be validated
|
47
50
|
def validate_actions(unchecked)
|
48
51
|
rejected = unchecked.reject { |action| action.is_a?(Symbol) }
|
49
52
|
NameError.new("invalid actions, got: #{rejected.join(", ")}") if rejected.size.positive?
|
50
53
|
end
|
51
54
|
|
52
|
-
|
53
|
-
#
|
55
|
+
# Validate `format` must be a Symbol and a valid MIME type
|
56
|
+
#
|
57
|
+
# @param unchecked the `format` to be validated
|
54
58
|
def validate_format(unchecked)
|
55
59
|
return ArgumentError.new("format must be a Symbol") unless unchecked.is_a?(Symbol)
|
56
60
|
|
57
61
|
NameError.new("invalid format, got: #{unchecked}") unless scene_formats.include?(unchecked)
|
58
62
|
end
|
59
63
|
|
60
|
-
|
61
|
-
#
|
64
|
+
# Validate `formats` must be an collection of Symbol which each of them is a valid MIME type
|
65
|
+
#
|
66
|
+
# @param unchecked the `formats` to be validated
|
62
67
|
def validate_formats(unchecked)
|
63
68
|
unfiltered = unchecked.to_set
|
64
69
|
filtered = unfiltered & scene_formats
|
@@ -67,8 +72,19 @@ module MimeActor
|
|
67
72
|
NameError.new("invalid formats, got: #{rejected.join(", ")}") if rejected.size.positive?
|
68
73
|
end
|
69
74
|
|
70
|
-
|
71
|
-
#
|
75
|
+
# Validate `klazz` must be a Class/Module or a String referencing a Class/Module
|
76
|
+
#
|
77
|
+
# @param unchecked the `klazz` to be validated
|
78
|
+
def validate_klazz(unchecked)
|
79
|
+
return if unchecked.is_a?(Module) || unchecked.is_a?(String)
|
80
|
+
|
81
|
+
ArgumentError.new("#{unchecked.inspect} must be a Class/Module or a String referencing a Class/Module")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Validate `with` or `block` must be provided and if `with` is provided, it must be a Symbol or Proc
|
85
|
+
#
|
86
|
+
# @param unchecked the `with` to be validated
|
87
|
+
# @param block the `block` to be valiated
|
72
88
|
def validate_with(unchecked, block)
|
73
89
|
if unchecked.present? && block.present?
|
74
90
|
return ArgumentError.new("provide either the with: keyword argument or a block")
|
@@ -76,9 +92,7 @@ module MimeActor
|
|
76
92
|
unless unchecked.present? || block.present?
|
77
93
|
return ArgumentError.new("provide the with: keyword argument or a block")
|
78
94
|
end
|
79
|
-
|
80
|
-
return if block.present?
|
81
|
-
return if unchecked.is_a?(Proc) || unchecked.is_a?(Symbol)
|
95
|
+
return if block.present? || unchecked.is_a?(Proc) || unchecked.is_a?(Symbol)
|
82
96
|
|
83
97
|
ArgumentError.new("with handler must be a Symbol or Proc, got: #{unchecked.inspect}")
|
84
98
|
end
|
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.
|
4
|
+
version: 0.6.0
|
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-
|
11
|
+
date: 2024-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- ".rspec"
|
64
64
|
- ".rubocop.yml"
|
65
65
|
- ".ruby-version"
|
66
|
+
- ".yardopts"
|
66
67
|
- COMPARE.md
|
67
68
|
- LICENSE
|
68
69
|
- README.md
|