twirp_rails 0.4.1 → 0.4.6

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: f7fbba3b1fe02ffed0c06b8a421f52577aab8634e0c3628c079721415c22df56
4
- data.tar.gz: 25ab97b4b24fd79ea5c338bbef35f124e082c3ce34a9588b0d66658858936f77
3
+ metadata.gz: 81fc1779265896c8e94b3e133dcb859f9cb88b8c50b243887ba40894ccfb5840
4
+ data.tar.gz: 481e078b49b5ffce44787f011e8702919efc0c6c1e657c14dd13e13d08065b78
5
5
  SHA512:
6
- metadata.gz: 11e6b0f20cfc055c2b0d89b06e7a79011b3ca28b5d0f4456d8872b62c67e6c22e8ca50728f6d1c3700fbf8c6bc04b5bcef0245c37392eb3f687b1329603446d2
7
- data.tar.gz: 2ee3fb02db058cea267475e4e872cc5049f732a3877a4454677ff9b4cbf9445f2c83b00fc654fae274f8994d822cdefdabb2656c178c886070ccd9ef02fd29fb
6
+ metadata.gz: 13fd0e6576cb5189487ffe8cfd48c7443faaf4ab94bfdb9c7500d2d7104ddf3cab9a4a0f74acce5e80616c6e998c3b757c75ece1fb0e62d59b3c6fc5ff71afa4
7
+ data.tar.gz: 281573e3920d9c57f7089ac0b2d5fdf418c70a30de16845ea6ec719b1d7753fac00862022523262abff254e086f60be4f09d97aa1bce38d36a09bf0c266a7d53
@@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 0.4.4 - 2020-05-05
8
+
9
+ ### Added
10
+
11
+ - ability to translate twirp errors to exceptions and vise versa.
12
+
13
+ ## 0.4.3 - 2020-04-14
14
+
15
+ ### Fixed
16
+
17
+ - autorequire all ruby files from `lib/twirp_clients` folder.
18
+
19
+ ## 0.4.2 - 2020-04-01
20
+
21
+ ### Added
22
+
23
+ - `to_twirp` extension use model method unless attribute found
24
+
7
25
  ## 0.4.1 - 2020-03-30
8
26
 
9
27
  ### Added
@@ -1,35 +1,35 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- twirp_rails (0.4.1)
4
+ twirp_rails (0.4.5)
5
5
  railties (~> 6.0)
6
6
  twirp (~> 1)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionpack (6.0.2.1)
12
- actionview (= 6.0.2.1)
13
- activesupport (= 6.0.2.1)
11
+ actionpack (6.0.3.1)
12
+ actionview (= 6.0.3.1)
13
+ activesupport (= 6.0.3.1)
14
14
  rack (~> 2.0, >= 2.0.8)
15
15
  rack-test (>= 0.6.3)
16
16
  rails-dom-testing (~> 2.0)
17
17
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
18
- actionview (6.0.2.1)
19
- activesupport (= 6.0.2.1)
18
+ actionview (6.0.3.1)
19
+ activesupport (= 6.0.3.1)
20
20
  builder (~> 3.1)
21
21
  erubi (~> 1.4)
22
22
  rails-dom-testing (~> 2.0)
23
23
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
24
- activesupport (6.0.2.1)
24
+ activesupport (6.0.3.1)
25
25
  concurrent-ruby (~> 1.0, >= 1.0.2)
26
26
  i18n (>= 0.7, < 2)
27
27
  minitest (~> 5.1)
28
28
  tzinfo (~> 1.1)
29
- zeitwerk (~> 2.2)
29
+ zeitwerk (~> 2.2, >= 2.2.2)
30
30
  builder (3.2.4)
31
31
  coderay (1.1.2)
32
- concurrent-ruby (1.1.5)
32
+ concurrent-ruby (1.1.6)
33
33
  crass (1.0.6)
34
34
  diff-lcs (1.3)
35
35
  erubi (1.9.0)
@@ -38,22 +38,22 @@ GEM
38
38
  generator_spec (0.9.4)
39
39
  activesupport (>= 3.0.0)
40
40
  railties (>= 3.0.0)
41
- google-protobuf (3.11.4-universal-darwin)
41
+ google-protobuf (3.12.0)
42
42
  i18n (1.8.2)
43
43
  concurrent-ruby (~> 1.0)
44
- loofah (2.4.0)
44
+ loofah (2.5.0)
45
45
  crass (~> 1.0.2)
46
46
  nokogiri (>= 1.5.9)
47
47
  method_source (0.9.2)
48
48
  mini_portile2 (2.4.0)
49
- minitest (5.14.0)
49
+ minitest (5.14.1)
50
50
  multipart-post (2.1.1)
51
- nokogiri (1.10.8)
51
+ nokogiri (1.10.9)
52
52
  mini_portile2 (~> 2.4.0)
53
53
  pry (0.12.2)
54
54
  coderay (~> 1.1.0)
55
55
  method_source (~> 0.9.0)
56
- rack (2.1.1)
56
+ rack (2.2.2)
57
57
  rack-test (1.1.0)
58
58
  rack (>= 1.0, < 3)
59
59
  rails-dom-testing (2.0.3)
@@ -61,13 +61,13 @@ GEM
61
61
  nokogiri (>= 1.6)
62
62
  rails-html-sanitizer (1.3.0)
63
63
  loofah (~> 2.3)
64
- railties (6.0.2.1)
65
- actionpack (= 6.0.2.1)
66
- activesupport (= 6.0.2.1)
64
+ railties (6.0.3.1)
65
+ actionpack (= 6.0.3.1)
66
+ activesupport (= 6.0.3.1)
67
67
  method_source
68
68
  rake (>= 0.8.7)
69
69
  thor (>= 0.20.3, < 2.0)
70
- rake (10.5.0)
70
+ rake (13.0.1)
71
71
  rspec (3.9.0)
72
72
  rspec-core (~> 3.9.0)
73
73
  rspec-expectations (~> 3.9.0)
@@ -91,12 +91,12 @@ GEM
91
91
  rspec-support (3.9.2)
92
92
  thor (1.0.1)
93
93
  thread_safe (0.3.6)
94
- twirp (1.4.1)
95
- faraday (~> 0)
94
+ twirp (1.5.0)
95
+ faraday (< 2)
96
96
  google-protobuf (~> 3.0, >= 3.0.0)
97
- tzinfo (1.2.6)
97
+ tzinfo (1.2.7)
98
98
  thread_safe (~> 0.1)
99
- zeitwerk (2.2.2)
99
+ zeitwerk (2.3.0)
100
100
 
101
101
  PLATFORMS
102
102
  ruby
@@ -105,7 +105,7 @@ DEPENDENCIES
105
105
  bundler (~> 1.17)
106
106
  generator_spec (~> 0.9)
107
107
  pry (~> 0.12)
108
- rake (~> 10.0)
108
+ rake (~> 13.0)
109
109
  rspec (~> 3.0)
110
110
  rspec-rails (~> 3.0)
111
111
  twirp_rails!
data/README.md CHANGED
@@ -9,6 +9,7 @@ TwirpRails helps to use [twirp-ruby gem](https://github.com/twitchtv/twirp-ruby)
9
9
  * `mount_twirp` route helper to mount handlers
10
10
  * `rpc` helper to dry your handlers specs
11
11
  * ability to log twirp calls by Rails logger
12
+ * DSL to translate handler exceptions to twirp errors and client twirp errors to ruby exceptions
12
13
 
13
14
  ## Installation
14
15
 
@@ -151,6 +152,53 @@ generated by
151
152
  $ rails g twirp:init
152
153
  ```
153
154
 
155
+ ## Exception handling
156
+
157
+ Translate handler exceptions to twirp errors and client twirp errors to ruby exceptions.
158
+
159
+ This feature allow to use ruby style exception handling flow in ruby code.
160
+
161
+ Create class to describe translate error rules
162
+ ```ruby
163
+ class ErrorTranslator < TwirpRails::ErrorHandling::Base
164
+ # rules to translate exception raised by handler to twirp
165
+ translate_exception ArgumentError, with: :invalid_argument
166
+ translate_exception ActiveRecord::NotFound do |exception, handler|
167
+ Twirp::Error.not_found
168
+ end
169
+
170
+ # rules to translate twirp errors returned from client to exception
171
+ translate_error :invalid_argument, with: ArgumentError
172
+ translate_error :not_found do |error, client|
173
+ ActiveRecord::NotFound.new(error.msg)
174
+ end
175
+ end
176
+ ```
177
+
178
+ And configure TwirpRails to use it:
179
+ ```ruby
180
+ # config/initializers/twirp_ruby.rb
181
+ # ...
182
+ config.twirp_exception_translator_class = 'ErrorTranslator'
183
+ # ...
184
+ ```
185
+
186
+ Services mounted by ```mount_twirp``` translates raised exception to twirp errors by this rules.
187
+
188
+ To raise errors by clients, you should create client by `TwirpRails.client`
189
+
190
+ ```ruby
191
+ client = TwirpRails.client(PeopleClient, 'http://localhost:3000/twirp')
192
+
193
+ client.get_name(uid: 'not found').error
194
+ # Twirp::Error code:not_found msg:"Couldn't find User with 'uid'='not found'"
195
+ client.get_name(uid: 'not found').data.name # NoMethodError: undefined method `name' for nil:NilClass
196
+
197
+ # use bang method to raise translated error and didn't check each twirp call result error
198
+ client.get_name!(uid: 'not found').data.name # ActiveRecord::NotFound: undefined method `name' for nil:NilClass
199
+ ```
200
+
201
+
154
202
  ## API acronym
155
203
 
156
204
  Gem adds inflector acronym `API` to correct using services with suffix `API`.
@@ -5,6 +5,7 @@ require 'twirp_rails/engine'
5
5
  require 'twirp_rails/generators/generators'
6
6
  require 'twirp_rails/active_record_extension'
7
7
  require 'twirp_rails/log_subscriber'
8
+ require 'twirp_rails/error_handling/error_handling'
8
9
 
9
10
  module TwirpRails
10
11
  class Error < StandardError; end
@@ -61,6 +62,8 @@ module TwirpRails
61
62
  config_param :purge_old_twirp_code, true
62
63
 
63
64
  config_param :add_api_acronym, true
65
+
66
+ config_param :twirp_exception_translator_class, nil
64
67
  end
65
68
 
66
69
  def self.configuration
@@ -119,4 +122,21 @@ module TwirpRails
119
122
 
120
123
  Time.zone.at seconds
121
124
  end
125
+
126
+ # Utility for converting a Ruby Time instance to a
127
+ # Google::Protobuf::Timestamp.
128
+ #
129
+ # @param time [Time] The Time to be converted.
130
+ #
131
+ # @return [Google::Protobuf::Timestamp] The converted
132
+ # Google::Protobuf::Timestamp.
133
+ def self.time_to_timestamp(time)
134
+ Google::Protobuf::Timestamp.new(seconds: time.to_i, nanos: time.nsec)
135
+ end
136
+
137
+ def self.client(klass, url)
138
+ client = klass.new(url)
139
+
140
+ TwirpRails::ErrorHandling.wrap_client(client)
141
+ end
122
142
  end
@@ -26,29 +26,32 @@ module TwirpRails
26
26
  # used by relation method to_twirp
27
27
  # @param [Array|Class] fields_or_class - array of converted fields or message class to
28
28
  def to_twirp(*fields_or_class)
29
- fields = fields_or_class
30
- result = attributes
31
-
32
- if fields.empty? && self.class.twirp_message_class
33
- fields = [self.class.twirp_message_class]
29
+ if fields_or_class.empty? && self.class.twirp_message_class
30
+ to_twirp_as_class(self.class.twirp_message_class)
31
+ elsif fields_or_class.one? && fields_or_class.first.is_a?(Class)
32
+ to_twirp_as_class(fields_or_class.first)
33
+ elsif fields_or_class.any?
34
+ to_twirp_as_fields(fields_or_class)
35
+ else
36
+ attributes
34
37
  end
38
+ end
35
39
 
36
- if fields.one? && fields.first.is_a?(Class)
37
- message_class = fields.first
40
+ private
38
41
 
39
- unless message_class.respond_to?(:descriptor)
40
- raise "Class #{message_class} must me a protobuf message class"
41
- end
42
+ def to_twirp_as_class(klass)
43
+ unless klass.respond_to?(:descriptor)
44
+ raise "Class #{klass} must be a protobuf message class"
45
+ end
42
46
 
43
- # TODO performance optimization needed
44
- fields = message_class.descriptor.map &:name
47
+ # TODO performance optimization needed
48
+ to_twirp_as_fields(klass.descriptor.map &:name)
49
+ end
45
50
 
46
- result = result.slice(*fields)
47
- elsif fields.any?
48
- result = result.slice(*fields)
51
+ def to_twirp_as_fields(fields)
52
+ fields.each_with_object({}) do |field, h|
53
+ h[field] = attributes.fetch(field) { public_send(field) }
49
54
  end
50
-
51
- result
52
55
  end
53
56
  end
54
57
  end
@@ -0,0 +1,114 @@
1
+ require 'twirp'
2
+
3
+ module TwirpRails
4
+ module ErrorHandling
5
+ class Base
6
+ ExceptionHandler = Struct.new(:exception, :proc) do
7
+ def match?(exception)
8
+ exception.is_a?(self.exception)
9
+ end
10
+
11
+ def handle(exception, handler)
12
+ proc.call(exception, handler)
13
+ end
14
+
15
+ def process(exception, handler)
16
+ match?(exception) ? handle(exception, handler) : nil
17
+ end
18
+ end
19
+
20
+ ErrorHandler = Struct.new(:code, :proc) do
21
+ def match?(error)
22
+ error.code == self.code
23
+ end
24
+
25
+ def handle(error, client)
26
+ proc.call(error, client)
27
+ end
28
+
29
+ def process(error, client)
30
+ match?(error) ? handle(error, client) : nil
31
+ end
32
+ end
33
+
34
+ class << self
35
+ # translate_exception InvalidArgument, :invalid_argument
36
+ #
37
+ # translate_exception StandardError { |exception, service| Twirp::Error.internal_with exception }
38
+ def translate_exception(*exceptions, with: nil, &block)
39
+ raise 'unexpected with and block' if block_given? && with
40
+ raise 'with or block must be defined' unless block_given? || with
41
+
42
+
43
+ proc = if with
44
+ raise "invalid twirp code #{with}" unless ::Twirp::ERROR_CODES.include?(with)
45
+
46
+ proc do |exception, _service|
47
+ ::Twirp::Error.new(with, exception.message).tap { |t| t.cause = exception }
48
+ end
49
+ else
50
+ proc { |exception, service| block.call(exception, service) }
51
+ end
52
+
53
+ exceptions.each do |exception|
54
+ exception_handlers << ExceptionHandler.new(exception, proc)
55
+ end
56
+ end
57
+
58
+ # translate_error :invalid_argument, InvalidArgument
59
+ #
60
+ # translate_error :internal_error { |error, client| StandardError.new(error.msg) }
61
+ def translate_error(*codes, with: nil, &block)
62
+ raise 'unexpected with and block' if block_given? && with.nil?
63
+ raise 'with or block must be defined' unless block_given? || !with.nil?
64
+ raise "invalid twirp code(s) #{codes - ::Twirp::ERROR_CODES}" if (codes - ::Twirp::ERROR_CODES).any?
65
+
66
+ proc = if with
67
+ raise 'with should be a exception class' unless with.is_a?(Class)
68
+
69
+ proc { |error, _client| with.new error.msg }
70
+ else
71
+ proc { |error, client| block.call(error, client) }
72
+ end
73
+
74
+ codes.each do |code|
75
+ error_handlers << ErrorHandler.new(code, proc)
76
+ end
77
+ end
78
+
79
+ def exception_handlers
80
+ @exception_handlers ||= []
81
+ end
82
+
83
+ def error_handlers
84
+ @error_handlers ||= []
85
+ end
86
+
87
+ def exception_to_twirp(exception, handler)
88
+ result = nil
89
+
90
+ exception_handlers.take_while do |exception_handler|
91
+ result = exception_handler.process(exception, handler)
92
+
93
+ result.nil?
94
+ end
95
+
96
+ result || ::Twirp::Error.internal_with(exception)
97
+ end
98
+
99
+ def twirp_to_exception(error, client)
100
+ result = nil
101
+
102
+ error_handlers.take_while do |handler|
103
+ result = handler.process(error, client)
104
+
105
+ result.nil?
106
+ end
107
+
108
+ result || StandardError.new(error.msg)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+
@@ -0,0 +1,2 @@
1
+ require 'twirp_rails/error_handling/base'
2
+ require 'twirp_rails/error_handling/error_handling_factory'
@@ -0,0 +1,82 @@
1
+ module TwirpRails
2
+ class ErrorHandlingFactory
3
+ class HandlerProxy
4
+ attr_reader :handler, :translator_class
5
+
6
+ def initialize(handler, translator_class)
7
+ @handler = handler
8
+ @translator_class = translator_class
9
+ end
10
+
11
+ # rubocop:disable Style/MethodMissingSuper
12
+ def method_missing(method, *args)
13
+ handler.public_send method, *args
14
+ rescue => e
15
+ translator_class.exception_to_twirp(e, handler)
16
+ end
17
+ # rubocop:enable Style/MethodMissingSuper
18
+
19
+ def respond_to_missing?(method, include_all = false)
20
+ handler.respond_to?(method, include_all)
21
+ end
22
+ end
23
+
24
+ class ClientProxy
25
+ attr_reader :client, :translator_class
26
+
27
+ def initialize(client, translator_class)
28
+ @client = client
29
+ @translator_class = translator_class
30
+ end
31
+
32
+ def raise_on_error(twirp_result)
33
+ if twirp_result.error
34
+ exception = translator_class.twirp_to_exception(twirp_result.error)
35
+ raise exception
36
+ else
37
+ twirp_result
38
+ end
39
+ end
40
+
41
+ # rubocop:disable Style/MethodMissingSuper
42
+ def method_missing(method, *args)
43
+ if method =~ /!$/
44
+ # when we call a bang version of client method - raise exception translated from error
45
+ method = method[0..-2]
46
+ raise_on_error client.public_send(method, args)
47
+ else
48
+ client.public_send method, args
49
+ end
50
+ end
51
+ # rubocop:enable Style/MethodMissingSuper
52
+
53
+ def respond_to_missing?(method, include_all = false)
54
+ handler.respond_to?(method, include_all)
55
+ end
56
+ end
57
+
58
+ class << self
59
+ attr_reader :translator_class
60
+
61
+ def wrap_handler(handler)
62
+ enable_handling? ? HandlerProxy.new(handler, translator_class) : handler
63
+ end
64
+
65
+ def wrap_client(client)
66
+ enable_handling? ? ClientProxy.new(client, translator_class) : client
67
+ end
68
+
69
+ def enable_handling?
70
+ if @enable_handling.nil?
71
+ if (@translator_class = TwirpRails.configuration.twirp_exception_translator_class)
72
+ @translator_class = @translator_class.constantize unless @translator_class.is_a?(Class)
73
+ @enable_handling = true
74
+ else
75
+ @enable_handling = false
76
+ end
77
+ end
78
+ @enable_handling
79
+ end
80
+ end
81
+ end
82
+ end
@@ -25,4 +25,18 @@ TwirpRails.configure do |config|
25
25
  #
26
26
  # Add API acronym to inflector
27
27
  # config.add_api_acronym = true
28
+ #
29
+ # Translate exceptions to Twirp::Error on services and
30
+ # Twirp::Error to exceptions. To use service translation you
31
+ # should mount service via mount_twirp. To use client translation
32
+ # create client via TwirpRails.client(ClientClass, url) and
33
+ # call bang methods. E.g. client.hello! throws exception if returns error.
34
+ #
35
+ # class SampleTranslator < TwirpRails::ErrorHandling::Base
36
+ # translate_exception Mongoid::Errors::DocumentNotFound, with: :not_found
37
+ # translate_error :not_found, with: Mongoid::Errors::DocumentNotFound
38
+ # end
39
+ # config.twirp_exception_translator_class = 'SampleTranslator'
40
+ # default:
41
+ # config.twirp_exception_translator_class = nil
28
42
  end
@@ -25,7 +25,7 @@ module TwirpRails
25
25
  raise 'twirp service name required'
26
26
  end
27
27
 
28
- service = service_class.new(handler.new)
28
+ service = service_class.new(ErrorHandlingFactory.wrap_handler(handler.new))
29
29
  Helper.run_create_hooks service
30
30
 
31
31
  if scope
@@ -65,7 +65,7 @@ module TwirpRails
65
65
  end
66
66
 
67
67
  included do
68
- let(:handler) { described_class.new }
68
+ let(:handler) { TwirpRails::ErrorHandlingFactory.wrap_handler(described_class.new) }
69
69
  let(:service) { service_class.new(handler) }
70
70
  end
71
71
  end
@@ -4,7 +4,7 @@ module TwirpRails
4
4
  # protoc generates require without path in a _pb files
5
5
  $LOAD_PATH.unshift(twirp_path) unless $LOAD_PATH.include?(twirp_path)
6
6
 
7
- Dir.glob(Rails.root.join('lib/twirp/**/*_twirp.rb')).sort.each do |file|
7
+ Dir.glob(Rails.root.join(twirp_path, '**/*_twirp.rb')).sort.each do |file|
8
8
  require file
9
9
  end
10
10
  end
@@ -1,3 +1,3 @@
1
1
  module TwirpRails
2
- VERSION = '0.4.1'.freeze
2
+ VERSION = '0.4.6'.freeze
3
3
  end
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency 'railties', '~> 6.0'
27
27
 
28
28
  spec.add_development_dependency 'bundler', '~> 1.17'
29
- spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rake', '~> 13.0'
30
30
  spec.add_development_dependency 'rspec', '~> 3.0'
31
31
  spec.add_development_dependency 'rspec-rails', '~> 3.0'
32
32
  spec.add_development_dependency 'generator_spec', '~> 0.9'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twirp_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandr Zimin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-30 00:00:00.000000000 Z
11
+ date: 2020-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: twirp
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -142,6 +142,9 @@ files:
142
142
  - lib/twirp_rails.rb
143
143
  - lib/twirp_rails/active_record_extension.rb
144
144
  - lib/twirp_rails/engine.rb
145
+ - lib/twirp_rails/error_handling/base.rb
146
+ - lib/twirp_rails/error_handling/error_handling.rb
147
+ - lib/twirp_rails/error_handling/error_handling_factory.rb
145
148
  - lib/twirp_rails/generators/generators.rb
146
149
  - lib/twirp_rails/generators/twirp/USAGE
147
150
  - lib/twirp_rails/generators/twirp/clients/USAGE
@@ -179,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
182
  - !ruby/object:Gem::Version
180
183
  version: '0'
181
184
  requirements: []
182
- rubygems_version: 3.0.6
185
+ rubygems_version: 3.1.3
183
186
  signing_key:
184
187
  specification_version: 4
185
188
  summary: Use twirp-ruby from rails.