mime_actor 0.0.0.alpha → 0.1.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: 7a7d2b7b38b9bb1238267b58f57961e099fd114c9f4786d3300a1a7e74611bc7
4
- data.tar.gz: 3266040aa145d6a6fd2188bd9c9f00a5fe0f6b6e9fd1e165634778d53ae6a368
3
+ metadata.gz: 8e71c1193071831b1f09601cb8ea8909e1f7b2b6642dfdab1253f288df4717c2
4
+ data.tar.gz: 22c67a0d503292dffa976efb5fc467ab1e280abd59dd7b2058ea0b75759ca5bb
5
5
  SHA512:
6
- metadata.gz: ddb033cca592816fa6f22e05f51d94a3bf67918541ecdef2d24252e3e3d0bea0d00eeb8b69b6ab63f6b08c1cb9e82f73c288883f9d170a34539e78cf0acd0f30
7
- data.tar.gz: 4014b324249b3f865689426eef1e0314527ef1e8c9bf5d07728b2f3a10fb3c0cdba870fc3a40315e7323a972ab4f04a3193504ba483da37bc19e7eb3e5fbd926
6
+ metadata.gz: 04d272ad8c24f21fa92576969bf6e434a3c65c46dfb9e39ddfb7e9b80b7847055a21a9c5dc5e38274916af61be5fa9fcc08bd7e9612625a9a5992915ce4e14f5
7
+ data.tar.gz: 3d2f97f2b3ae25c7e64047629967932da4c0bceca4794f8b93fa87f98250e7a18256331ebdd24fe5ba5ca2d60eb9cb4a6349512da1040dbef0117a045277b76c
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.1
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # mime_actor
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/mime_actor.svg)](https://badge.fury.io/rb/mime_actor)
4
+ [![Build](https://github.com/ryancyq/mime_actor/actions/workflows/build.yml/badge.svg)](https://github.com/ryancyq/mime_actor/actions/workflows/build.yml)
5
+
3
6
  Action rendering and rescue with mime type via configuration in actionpack
4
7
 
5
8
  ## Installation
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/concern'
4
+ require 'active_support/configurable'
3
5
  require "active_support/core_ext/array/extract_options"
4
6
  require "active_support/core_ext/array/wrap"
5
7
  require "active_support/core_ext/hash/indifferent_access"
6
- require 'action_controller'
7
- require 'action_dispatch'
8
+ require "active_support/core_ext/module/attribute_accessors"
9
+ require 'abstract_controller/logger'
10
+ require 'abstract_controller/rendering'
11
+ require 'action_controller/metal/mime_responds'
8
12
 
9
13
  module MimeActor
10
14
  module Formatter
@@ -14,9 +18,6 @@ module MimeActor
14
18
  include AbstractController::Rendering # required by MimeResponds
15
19
  include ActionController::MimeResponds
16
20
 
17
- SUPPORTED_MIME_TYPES = Mime::SET.symbols.to_set
18
- private_constant :SUPPORTED_MIME_TYPES
19
-
20
21
  included do
21
22
  mattr_accessor :action_formatters, instance_writer: false, default: ActiveSupport::HashWithIndifferentAccess.new
22
23
  mattr_accessor :raise_on_missing_action_formatter, instance_writer: false, default: false
@@ -61,7 +62,17 @@ module MimeActor
61
62
  formatters.each do |formatter|
62
63
  next unless actor = find_actor(action_name, formatter)
63
64
 
64
- collector.public_send(formatter, &actor)
65
+ dispatch = unless self.class.respond_to?(:dispatch_act)
66
+ actor
67
+ else
68
+ self.class.public_send(:dispatch_act,
69
+ action: action_name.to_sym,
70
+ format: formatter.to_sym,
71
+ context: self,
72
+ &actor
73
+ )
74
+ end
75
+ collector.public_send(formatter, &dispatch)
65
76
  end
66
77
  end
67
78
  end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+ require 'active_support/configurable'
5
+ require "active_support/core_ext/module/attribute_accessors"
6
+ require 'abstract_controller/logger'
7
+
8
+ module MimeActor
9
+ module Rescuer
10
+ extend ActiveSupport::Concern
11
+ include ActiveSupport::Configurable
12
+ include AbstractController::Logger
13
+
14
+ included do
15
+ mattr_accessor :actor_rescuers, instance_writer: false, default: []
16
+ end
17
+
18
+ module ClassMethods
19
+ def rescue_act_from(*klazzes, format: nil, action: nil, with: nil, &block)
20
+ unless with
21
+ raise ArgumentError, "Provide the with: keyword argument or a block" unless block_given?
22
+ with = block
23
+ end
24
+ raise ArgumentError, "Rescue handler can only be Symbol/Proc" unless with.is_a?(Proc) || with.is_a?(Symbol)
25
+
26
+ if format.present?
27
+ case format
28
+ when Symbol
29
+ raise ArgumentError, "Unsupported format: #{format}" unless SUPPORTED_MIME_TYPES.include?(format.to_sym)
30
+ when Enumerable
31
+ unfiltered = format.to_set
32
+ filtered = unfiltered & SUPPORTED_MIME_TYPES
33
+ rejected = unfiltered - filtered
34
+ raise ArgumentError, "Unsupported formats: #{rejected.join(', ')}" if rejected.size.positive?
35
+ else
36
+ raise ArgumentError, "Format filter can only be Symbol/Enumerable"
37
+ end
38
+ end
39
+
40
+ if action.present?
41
+ message = "Action filter can only be Symbol/Enumerable"
42
+ raise ArgumentError, message unless action.is_a?(Symbol) || action.is_a?(Enumerable)
43
+ end
44
+
45
+ klazzes.each do |klazz|
46
+ error = if klazz.is_a?(Module)
47
+ klazz.name
48
+ elsif klazz.is_a?(String)
49
+ klazz
50
+ else
51
+ raise ArgumentError, "#{klazz.inspect} must be a class/module or a String referencing a class/module"
52
+ end
53
+
54
+ # append at the end because strategies are read in reverse.
55
+ self.actor_rescuers << [error, format, action, with]
56
+ end
57
+ end
58
+
59
+ def dispatch_act(action: nil, format: nil, context: self, &block)
60
+ lambda do
61
+ case block
62
+ when Proc
63
+ context.instance_exec(&block)
64
+ else
65
+ block.call
66
+ end
67
+ rescue Exception => ex
68
+ rescue_actor(ex, format:, action:, context:) || raise
69
+ end
70
+ end
71
+
72
+ def rescue_actor(error, action: nil, format: nil, context: self, visited: [])
73
+ visited << error
74
+
75
+ if rescuer = dispatch_rescuer(error, format:, action:, context:)
76
+ rescuer.call(error, format, action)
77
+ error
78
+ elsif error && error.cause && !visited.include?(error.cause)
79
+ rescue_actor(error.cause, format:, action:, context:, visited:)
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def dispatch_rescuer(error, format:, action:, context:)
86
+ case rescuer = find_rescuer(error, format:, action:)
87
+ when Symbol
88
+ rescuer_method = context.method(rescuer)
89
+ case rescuer_method.arity
90
+ when 0
91
+ -> e,f,a { rescuer_method.call }
92
+ when 1
93
+ -> e,f,a { rescuer_method.call(e) }
94
+ when 2
95
+ -> e,f,a { rescuer_method.call(e,f) }
96
+ else
97
+ -> e,f,a { rescuer_method.call(e,f,a) }
98
+ end
99
+ when Proc
100
+ case rescuer.arity
101
+ when 0
102
+ -> e,f,a { context.instance_exec(&rescuer) }
103
+ when 1
104
+ -> e,f,a { context.instance_exec(e, &rescuer) }
105
+ when 2
106
+ -> e,f,a { context.instance_exec(e, f, &rescuer) }
107
+ else
108
+ -> e,f,a { context.instance_exec(e, f, a, &rescuer) }
109
+ end
110
+ end
111
+ end
112
+
113
+ def find_rescuer(error, format:, action:)
114
+ return unless error
115
+
116
+ *_, rescuer = actor_rescuers.reverse_each.detect do |rescuee, format_filter, action_filter|
117
+ next if action_filter.present? && !Array.wrap(action_filter).include?(action)
118
+ next if format_filter.present? && !Array.wrap(format_filter).include?(format)
119
+ next unless klazz = constantize_rescuee(rescuee)
120
+
121
+ klazz === error # klazz is a member of error
122
+ end
123
+ rescuer
124
+ end
125
+
126
+ def constantize_rescuee(class_or_name)
127
+ case class_or_name
128
+ when String, Symbol
129
+ begin
130
+ const_get(class_or_name)
131
+ rescue NameError
132
+ class_or_name.safe_constantize
133
+ end
134
+ else
135
+ class_or_name
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -11,9 +11,9 @@ module MimeActor
11
11
 
12
12
  module VERSION
13
13
  MAJOR = 0
14
- MINOR = 0
15
- BUILD = 0
16
- PRE = "alpha"
14
+ MINOR = 1
15
+ BUILD = 0
16
+ PRE = nil
17
17
 
18
18
  STRING = [MAJOR, MINOR, BUILD, PRE].compact.join(".")
19
19
  end
data/lib/mime_actor.rb CHANGED
@@ -10,4 +10,10 @@ module MimeActor
10
10
 
11
11
  autoload :Formatter
12
12
  include Formatter
13
+
14
+ autoload :Rescuer
15
+ include Rescuer
16
+
17
+ SUPPORTED_MIME_TYPES = Mime::SET.symbols.to_set
18
+ private_constant :SUPPORTED_MIME_TYPES
13
19
  end
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.0.0.alpha
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Chang
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-21 00:00:00.000000000 Z
11
+ date: 2024-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -89,11 +89,13 @@ extra_rdoc_files: []
89
89
  files:
90
90
  - ".rspec"
91
91
  - ".rubocop.yml"
92
+ - ".ruby-version"
92
93
  - LICENSE
93
94
  - README.md
94
95
  - Rakefile
95
96
  - lib/mime_actor.rb
96
97
  - lib/mime_actor/formatter.rb
98
+ - lib/mime_actor/rescuer.rb
97
99
  - lib/mime_actor/version.rb
98
100
  - sig/mime_actor.rbs
99
101
  homepage: https://github.com/ryancyq/mime_actor
@@ -104,7 +106,7 @@ metadata:
104
106
  homepage_uri: https://github.com/ryancyq/mime_actor
105
107
  source_code_uri: https://github.com/ryancyq/mime_actor
106
108
  changelog_uri: https://github.com/ryancyq/mime_actor/blob/main/CHANGELOG.md
107
- post_install_message:
109
+ post_install_message:
108
110
  rdoc_options: []
109
111
  require_paths:
110
112
  - lib
@@ -112,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
112
114
  requirements:
113
115
  - - ">="
114
116
  - !ruby/object:Gem::Version
115
- version: 2.7.0
117
+ version: 3.1.0
116
118
  required_rubygems_version: !ruby/object:Gem::Requirement
117
119
  requirements:
118
120
  - - ">="
@@ -120,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
122
  version: '0'
121
123
  requirements: []
122
124
  rubygems_version: 3.5.9
123
- signing_key:
125
+ signing_key:
124
126
  specification_version: 4
125
127
  summary: action rendering and rescue with mime type via configuration in actionpack
126
128
  test_files: []