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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 709cab49cc347653da124ec9147c7527b96f71df08059b6eab45a5d9b5b06888
4
- data.tar.gz: ac9a75000c8711550971fa0d6e4f0ba3bc2b9e706ebd1654702df1b56d3e0f5d
3
+ metadata.gz: 031455cd4203f02b1760129516e1a8722af2f84d7580cf1799f886d98262cdea
4
+ data.tar.gz: 78b2841148310600b408fd3d2932741ab61280f24afb28f0b251e62bcba91419
5
5
  SHA512:
6
- metadata.gz: 40fe1d6ba3560b836c12ec423d8285497f2576f231a385ecf910942cedd8be7c36ea1d20077283f2aa336c0aa1beab92a6472b998a63fde4a3b9de1e71f5a9c3
7
- data.tar.gz: 5dc2dcc8697d65e386bf47f898b4ed85b8fe7d364ddfce84be873b966653c713e788c994a57e879e439ae1f6401e69092905dd88319a52c94f8c1be817daa1ca
6
+ metadata.gz: 2852a58bb4dc628d293e6d5974b452144496be454a2a594aec90baaffcf5fbbcdd096745778853f36cc5e8ef4eb577340175bd76533ba2be1852799ddf5cc2a6
7
+ data.tar.gz: f548c1d8fe2c32a2aba34c4b9189e3e02272fdcfdc850d8b88e6cb6eea54514a1c95cc8ede181656f5ba0e92111f2566db1cbc98b647dd77f0922cd2ff1357be
data/.rubocop.yml CHANGED
@@ -19,6 +19,10 @@ Style/BlockComments:
19
19
  Metrics/AbcSize:
20
20
  Enabled: false
21
21
 
22
+ Metrics/BlockLength:
23
+ AllowedMethods:
24
+ - class_methods
25
+
22
26
  Metrics/CyclomaticComplexity:
23
27
  Enabled: false
24
28
 
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup markdown
2
+ lib/**/*.rb
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
- compose_scene :html, :json, on: :index
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
- compose_scene :html, :json, on: [:show, :update]
95
+ act_on_format :html, :json, on: [:show, :update]
96
96
 
97
- rescue_actor_from ActiveRecord::RecordNotFound, format: :json do |ex|
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
- rescue_actor_from ActiveRecord::RecordNotFound, format: :html, action: :show do |ex|
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
- compose_scene :html, :json, on: :index
20
- compose_scene :html, :json, on: [:show, :update]
19
+ act_on_format :html, :json, on: :index
20
+ act_on_format :html, :json, on: [:show, :update]
21
21
 
22
- rescue_actor_from ActiveRecord::RecordNotFound, format: :json do |ex|
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
- rescue_actor_from ActiveRecord::RecordNotFound, format: :html, action: :show do |ex|
26
+ rescue_act_from ActiveRecord::RecordNotFound, format: :html, action: :show do |ex|
27
27
  redirect_to events_path
28
28
  end
29
29
 
@@ -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
- # The core logic where rendering logics are collected as Proc through configuration and passed over to ActionController::MimeResponds
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)
@@ -10,7 +10,7 @@ require "active_support/tagged_logging"
10
10
 
11
11
  module MimeActor
12
12
  # # MimeActor Logging
13
- #
13
+ #
14
14
  # Provides a configurable logger.
15
15
  module Logging
16
16
  extend ActiveSupport::Concern
@@ -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 Action/Format.
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
- module ClassMethods
29
- ##
30
- # Registers a rescue handler for the given error classes with action/format filter
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
- # rescue_actor_from StandardError, format: :json, action: :show do |ex|
33
- # render status: :bad_request, json: { error: ex.message }
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
- # rescue_actor_from StandardError, format: :html, with: :handle_html_error
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 rescue_actor_from(*klazzes, action: nil, format: nil, with: nil, &block)
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
- if action.is_a?(Enumerable)
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
- if format.is_a?(Enumerable)
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
- error = case klazz
62
- when Module
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
- # The handled error will be returned to indicate successful handling
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
 
@@ -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 Action + Format definitions
16
+ # Scene provides configuration for `action` + `format` definitions
17
17
  #
18
- # compose_scene :html, on: :index
19
- # compose_scene :html, :json , on: [:index, :show]
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/format multiple times will overwrite previous Action + Format definitions.
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
- module ClassMethods
33
- ##
34
- # Register Action + Format definitions.
34
+ class_methods do
35
+ # Register `action` + `format` definitions.
35
36
  #
36
- # For each unique action being registered, it will have a corresponding method being defined.
37
- def compose_scene(*options)
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
- if !actions
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
- else
54
+ when Symbol, String
47
55
  validate!(:action, actions)
56
+ else
57
+ raise ArgumentError, "action is required"
48
58
  end
49
59
 
50
- options.each do |format|
51
- Array.wrap(actions).each do |action|
52
- action_defined = (instance_methods + private_instance_methods).include?(action.to_sym)
53
- raise MimeActor::ActionExisted, action if !acting_scenes.key?(action) && action_defined
60
+ Array.wrap(actions).each do |action|
61
+ options.each { |format| compose_scene(action, format) }
62
+ end
63
+ end
54
64
 
55
- acting_scenes[action] ||= Set.new
56
- acting_scenes[action] |= [format]
65
+ private
57
66
 
58
- next if action_defined
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
- class_eval(
61
- # def index
62
- # self.respond_to?(:start_scene) && self.start_scene(:index)
63
- # end
64
- <<-RUBY, __FILE__, __LINE__ + 1
65
- def #{action}
66
- self.respond_to?(:start_scene) && self.start_scene(:#{action})
67
- end
68
- RUBY
69
- )
70
- end
71
- end
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
@@ -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 helpers for actor lookup and invocation.
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
- module ClassMethods
26
- ##
27
- # Determine if the name belongs to a public instance method excluding methods inherited from ancesstors
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
- # Wraps the given block with lambda, rescue any error raised from the block via #rescue_actor if defined, otherwise, error will be re-raised
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
- # Call the actor method if defined, supports passing arguments to the actor method.
53
- #
54
- # If a block is given, the result from the actor method will be yieled to the block
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
@@ -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, format, and rescue handlers by default.
12
+ # Validator provides validation rules for `action`, `format`, and `with` handlers by default.
13
13
  #
14
- # # raise error when rule is violated
15
- # validate!(:action, action_param)
14
+ # @example Raise error when rule is violated
15
+ # validate!(:action, action_param)
16
16
  #
17
- # # return the error when rule is violated
18
- # ex = validate_action(action_param)
19
- # raise ex if error
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
- module ClassMethods
29
- ##
30
- # Raise the error returned by validator if present.
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
- # validate :action must be a Symbol
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
- # validate :actions must be an Array of Symbol
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
- # validate :format must be a Symbol + a valid MIME type
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
- # validate :formats must be an Array of Symbol which each of them is a valid MIME type
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
- # validate :with or &block must be provided + :with must be a Symbol or Proc
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
@@ -11,8 +11,8 @@ module MimeActor
11
11
 
12
12
  module VERSION
13
13
  MAJOR = 0
14
- MINOR = 5
15
- BUILD = 3
14
+ MINOR = 6
15
+ BUILD = 0
16
16
  PRE = nil
17
17
 
18
18
  STRING = [MAJOR, MINOR, BUILD, PRE].compact.join(".")
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.5.3
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-06-29 00:00:00.000000000 Z
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