action_controller-twirp 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22fa76662fce706d3efefc38981bfab8ed7cd01611e1d4de2bc8c7a8ad919e38
4
- data.tar.gz: 4479f03e25ef53f640feaaa9fb9e8c2e10e5202606f522da1949abbed88dfa5e
3
+ metadata.gz: ba5d8f3dbfc7dc8099def1e420b3a6c79cc2611df1295fad0c9e5f03ed3b1339
4
+ data.tar.gz: f2597df16242abd93b1ff1878b664db3f9e66cf63904e2030a47e000c32ba160
5
5
  SHA512:
6
- metadata.gz: b576978ee686292ac1150e876283101981094ce919e2d0c00bc202d7e5177badad3a9f29655aa3f7a6eed158e1ff02bbce89c8fb4998300cf4ba419f8a51729e
7
- data.tar.gz: b28a534f96ace98a8f2daad7bbe2e90f72cbce3533ad5133fadfa49aa0d4ab07006b649e79f0252e43be331868091255af951ae6934103a8659244684602dc4f
6
+ metadata.gz: ec99d0597b6d950cbf5f65c6900ef64ac855871520bb682d7f916a70aa1dcb6892152a190f487ab639098f4ba44757db9387a420ef22e603326ec08468964d3c
7
+ data.tar.gz: 780bf0fab5393d22940621111dfdf811c78007369c64b9a18cfa1f8e50b0adddf3300e07ef6a592605a936d987c481e73835e115109fccaa2a60e3b8ad6902d4
data/README.md CHANGED
@@ -51,13 +51,6 @@ Finally, implement rpc method your controller
51
51
  class UsersController < ApplicationController # :nodoc:
52
52
  include ActionController::Twirp
53
53
 
54
- rescue_from ActiveRecord::RecordNotFound do |e|
55
- twerr = Twirp::Error.not_found('The message',
56
- reason: e.class.name.demodulize,
57
- id: params[:id].to_s)
58
- render twirp_error: twerr
59
- end
60
-
61
54
  USERS = [
62
55
  { id: 1, name: 'Anna' },
63
56
  { id: 2, name: 'Reina' }
@@ -77,6 +70,48 @@ class UsersController < ApplicationController # :nodoc:
77
70
  end
78
71
  ```
79
72
 
73
+ ### Error handling
74
+
75
+ twirp-ruby eventually provides us with a rack app, which handles the exception and returns a response when an exception occurs.
76
+ Provide settings for exception handling, as the status code or body may be unexpected when an error occurs.
77
+
78
+ You can install initializer by rails generate command
79
+ ```sh
80
+ > bin/rails generate action_controller:twirp:install
81
+
82
+ > cat config/initializers/action_controller_twirp.rb
83
+ # frozen_string_literal: true
84
+
85
+ ActionController::Twirp::Config.setup do |config|
86
+ # Handle exceptions
87
+ # true: handling by ActionController::Twirp
88
+ # false: handling by Twirp::Service (default)
89
+ # config.handle_exceptions = false
90
+
91
+ # ---
92
+ # The following configurations ignore when handle_exceptions is false
93
+ # ---
94
+
95
+ # Mapping your exception classes and Twirp::Error::ERROR_CODES
96
+ # String => Symbol
97
+ # config.exception_codes = {
98
+ # 'ActiveRecord::RecordInvalid' => :invalid_argument,
99
+ # 'ActiveRecord::RecordNotFound' => :not_found,
100
+ # 'My::Exception' => :aborted,
101
+ # }
102
+
103
+ # Block to make Twirp::Error message when exception_codes exist
104
+ # config.build_message = ->(exception) {}
105
+
106
+ # Block to make Twirp::Error metadata. when exception_codes exist
107
+ # It MUST return Hash value
108
+ # config.build_metadata = ->(exception) {}
109
+
110
+ # Block to run additional process. e.g. logging
111
+ # config.on_exceptions = ->(exception) {}
112
+ end
113
+ ```
114
+
80
115
  ## Contributing
81
116
  Contribution directions go here.
82
117
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/module/attribute_accessors'
4
+
5
+ module ActionController
6
+ module Twirp
7
+ # Configration for ActionController::Twirp
8
+ module Config
9
+ # Handle exceptions
10
+ # true: handling by ActionController::Twirp
11
+ # false: handling by Twirp::Service
12
+ mattr_accessor :handle_exceptions, default: false
13
+
14
+ # ---
15
+ # The following configurations ignore when handle_exceptions is false
16
+ # ---
17
+
18
+ # Mapping your exception classes and Twirp::Error::ERROR_CODES
19
+ mattr_accessor :exception_codes, default: {}
20
+
21
+ # Block to make Twirp::Error message
22
+ mattr_accessor :build_message, default: ->(exception) {}
23
+
24
+ # Block to make Twirp::Error metadata
25
+ mattr_accessor :build_metadata, default: ->(exception) {}
26
+
27
+ # Block to run additional process. e.g. logging
28
+ mattr_accessor :on_exceptions, default: ->(exception) {}
29
+
30
+ def self.setup
31
+ yield self
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,19 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'action_controller/twirp/twirp_error_renderer'
4
3
  require 'action_dispatch/twirp/railtie'
5
4
 
6
5
  module ActionController
7
6
  module Twirp
8
7
  class Railtie < ::Rails::Railtie # :nodoc:
9
- initializer 'action_controller.twirp' do
10
- ActiveSupport.on_load(:action_controller) do
11
- ActionController::Renderers.add :twirp_error do |content, options|
12
- renderer = TwirpErrorRenderer.new(content, options)
13
- render(**renderer.to_render_option)
14
- end
15
- end
16
- end
17
8
  end
18
9
  end
19
10
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActionController
4
4
  module Twirp
5
- VERSION = '0.1.1'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'action_controller/twirp/version'
4
4
  require 'action_controller/twirp/railtie'
5
+ require 'action_controller/twirp/config'
5
6
 
6
7
  module ActionController
7
8
  # Module to execute your implemented methods on Twirp with Rails
@@ -10,9 +11,9 @@ module ActionController
10
11
 
11
12
  # Override it to call a twirp class from request path
12
13
  def send_action(*_args)
13
- twirp_service_class.raise_exceptions = true
14
+ twirp_service_class.raise_exceptions = Config.handle_exceptions
14
15
 
15
- status, header, body = twirp_service_class.new(self)&.call(request.env)
16
+ status, header, body = twirp_action
16
17
 
17
18
  response.status = status
18
19
  response.header.merge!(header)
@@ -25,5 +26,35 @@ module ActionController
25
26
  class_name = request.path.split('/')[-2].underscore.gsub('.', '/').classify
26
27
  @twirp_service_class = "#{class_name}Service".constantize
27
28
  end
29
+
30
+ def twirp_action
31
+ twirp_service_class.new(self)&.call(request.env)
32
+ rescue StandardError => e
33
+ begin
34
+ Config.on_exceptions.call(e)
35
+ rescue StandardError => hook_e
36
+ e = hook_e
37
+ end
38
+ twirp_error_response(e)
39
+ end
40
+
41
+ def twirp_error_response(exception)
42
+ twerr = twirp_error(exception)
43
+ twirp_service_class.error_response(twerr)
44
+ end
45
+
46
+ def twirp_error(exception)
47
+ if Config.exception_codes.key?(exception.class.to_s)
48
+ code = Config.exception_codes[exception.class.to_s]
49
+ message = Config.build_message.call(exception)
50
+ metadata = Config.build_metadata.call(exception)
51
+
52
+ ::Twirp::Error.public_send(code, message, metadata)
53
+ else
54
+ ::Twirp::Error.internal_with(exception)
55
+ end
56
+ rescue StandardError => e
57
+ ::Twirp::Error.internal_with(e)
58
+ end
28
59
  end
29
60
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionController
4
+ module Twirp
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base # :nodoc:
7
+ source_root File.expand_path('../../templates', __dir__)
8
+
9
+ desc 'Creates a ActionController::Twirp initializer'
10
+ def copy_initializer
11
+ template 'action_controller_twirp.rb', 'config/initializers/action_controller_twirp.rb'
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ ActionController::Twirp::Config.setup do |config|
4
+ # Handle exceptions
5
+ # true: handling by ActionTwirpRails
6
+ # false: handling by Twirp::Service (default)
7
+ # config.handle_exceptions = false
8
+
9
+ # ---
10
+ # The following configurations ignore when handle_exceptions is false
11
+ # ---
12
+
13
+ # Mapping your exception classes and Twirp::Error::ERROR_CODES
14
+ # String => Symbol
15
+ # config.exception_codes = {
16
+ # 'ActiveRecord::RecordInvalid' => :invalid_argument,
17
+ # 'ActiveRecord::RecordNotFound' => :not_found,
18
+ # 'My::Exception' => :aborted,
19
+ # }
20
+
21
+ # Block to make Twirp::Error message when exception_codes exist
22
+ # config.build_message = ->(exception) {}
23
+
24
+ # Block to make Twirp::Error metadata. when exception_codes exist
25
+ # It MUST return Hash value
26
+ # config.build_metadata = ->(exception) {}
27
+
28
+ # Block to run additional process. e.g. logging
29
+ # config.on_exceptions = ->(exception) {}
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_controller-twirp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kosuke Arisawa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-21 00:00:00.000000000 Z
11
+ date: 2022-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -63,11 +63,13 @@ files:
63
63
  - README.md
64
64
  - Rakefile
65
65
  - lib/action_controller/twirp.rb
66
+ - lib/action_controller/twirp/config.rb
66
67
  - lib/action_controller/twirp/railtie.rb
67
- - lib/action_controller/twirp/twirp_error_renderer.rb
68
68
  - lib/action_controller/twirp/version.rb
69
69
  - lib/action_dispatch/routing/mapper/twirp.rb
70
70
  - lib/action_dispatch/twirp/railtie.rb
71
+ - lib/generators/action_controller/twirp/install_generator.rb
72
+ - lib/generators/templates/action_controller_twirp.rb
71
73
  - lib/tasks/action_controller/twirp_tasks.rake
72
74
  homepage: https://github.com/arisawa/action_controller-twirp
73
75
  licenses:
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActionController
4
- module Twirp
5
- # Convert Twirp::Error to #render option
6
- class TwirpErrorRenderer
7
- # @param content [Twirp::Error] given as a value of :twirp_error key of render method.
8
- # @param options [Hash] options of render method.
9
- def initialize(content, options)
10
- unless content.is_a?(::Twirp::Error)
11
- raise ArgumentError, 'Only Twirp::Error instance can be specified'
12
- end
13
-
14
- @content = content
15
- @options = options.dup
16
- end
17
-
18
- def to_render_option
19
- {
20
- json: twirp_error.to_h,
21
- **@options.merge(status: status, content_type: content_type)
22
- }
23
- end
24
-
25
- private
26
-
27
- def twirp_error
28
- return @twirp_error if defined? @twirp_error
29
-
30
- code = @content.code
31
-
32
- @twirp_error = if ::Twirp::Error.valid_code?(code)
33
- @content
34
- else
35
- ::Twirp::Error.internal("Invalid code: #{code}", invalid_code: code.to_s)
36
- end
37
- end
38
-
39
- def status
40
- ::Twirp::ERROR_CODES_TO_HTTP_STATUS[twirp_error.code]
41
- end
42
-
43
- def content_type
44
- ::Twirp::Encoding::JSON
45
- end
46
- end
47
- end
48
- end