twirp_rails 0.4.0 → 0.4.1
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/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/README.md +41 -9
- data/lib/twirp_rails/engine.rb +4 -2
- data/lib/twirp_rails/generators/generators.rb +5 -0
- data/lib/twirp_rails/generators/twirp/clients/clients_generator.rb +31 -17
- data/lib/twirp_rails/generators/twirp/init/templates/twirp_rails.rb +7 -0
- data/lib/twirp_rails/generators/twirp/protoc_adapter.rb +65 -0
- data/lib/twirp_rails/generators/twirp/twirp_generator.rb +71 -40
- data/lib/twirp_rails/version.rb +1 -1
- data/lib/twirp_rails.rb +23 -4
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7fbba3b1fe02ffed0c06b8a421f52577aab8634e0c3628c079721415c22df56
|
4
|
+
data.tar.gz: 25ab97b4b24fd79ea5c338bbef35f124e082c3ce34a9588b0d66658858936f77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11e6b0f20cfc055c2b0d89b06e7a79011b3ca28b5d0f4456d8872b62c67e6c22e8ca50728f6d1c3700fbf8c6bc04b5bcef0245c37392eb3f687b1329603446d2
|
7
|
+
data.tar.gz: 2ee3fb02db058cea267475e4e872cc5049f732a3877a4454677ff9b4cbf9445f2c83b00fc654fae274f8994d822cdefdabb2656c178c886070ccd9ef02fd29fb
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,20 @@ 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.1 - 2020-03-30
|
8
|
+
|
9
|
+
### Added
|
10
|
+
|
11
|
+
- smart service detection - you can use `rails g twirp svc` if you `Svc` or
|
12
|
+
`SvcAPI` service described at `company/service/subservice/version/etc/svc_api.proto`
|
13
|
+
- Add `# :nocov:` comment to generated modules to avoid decrease coverage
|
14
|
+
- Improve generator console output and error handling
|
15
|
+
- `add_api_acronym` configuration option
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
- `protoc` path was cached on start and didn't reload with spring
|
20
|
+
|
7
21
|
## 0.4.0 - 2020-03-24
|
8
22
|
|
9
23
|
### Breaking changes
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -25,7 +25,7 @@ to install required protoc and twirp-ruby plugin.
|
|
25
25
|
|
26
26
|
### Generator
|
27
27
|
|
28
|
-
Create a proto file ```
|
28
|
+
Create a proto file ```rpc/people.proto```:
|
29
29
|
```proto
|
30
30
|
syntax = "proto3";
|
31
31
|
|
@@ -110,18 +110,14 @@ or run ```rails g twirp:rspec``` to do it automatically.
|
|
110
110
|
|
111
111
|
## Log twirp calls
|
112
112
|
|
113
|
-
By default, Rails logs only start of POST request. To get a more detailed log of twirp calls
|
113
|
+
By default, Rails logs only start of POST request. To get a more detailed log of twirp calls
|
114
|
+
use `config.log_twirp_calls` configuration option (default `true`).
|
114
115
|
|
115
|
-
|
116
|
-
# config/initializers/twirp_rails.rb
|
117
|
-
TwirpRails.log_twirp_calls!
|
118
|
-
```
|
119
|
-
|
120
|
-
You can customize log output by pass a block argument
|
116
|
+
You can customize log output by pass a proc.
|
121
117
|
|
122
118
|
```ruby
|
123
119
|
# config/initializers/twirp_rails.rb
|
124
|
-
|
120
|
+
config.log_twirp_calls = -> (event) do
|
125
121
|
twirp_call_info = {
|
126
122
|
duration: event.duration,
|
127
123
|
method: event.payload[:env][:rpc_method],
|
@@ -136,6 +132,42 @@ TwirpRails.log_twirp_calls! do |event|
|
|
136
132
|
end
|
137
133
|
```
|
138
134
|
|
135
|
+
## Generate clients
|
136
|
+
|
137
|
+
Clients generator calls `protoc` to generate code from all proto files from
|
138
|
+
`rpc_clients` directory to `lib/twirp_clients` (all files auto required on application startup).
|
139
|
+
|
140
|
+
Generator runs without options by executing
|
141
|
+
|
142
|
+
```
|
143
|
+
$ rails g twirp:clients
|
144
|
+
```
|
145
|
+
|
146
|
+
## Configuration
|
147
|
+
|
148
|
+
All configuration options (e.g. paths) can be customized via initializer file
|
149
|
+
generated by
|
150
|
+
```
|
151
|
+
$ rails g twirp:init
|
152
|
+
```
|
153
|
+
|
154
|
+
## API acronym
|
155
|
+
|
156
|
+
Gem adds inflector acronym `API` to correct using services with suffix `API`.
|
157
|
+
`API` suffix required by `prototool` linter with `uber2` rules. You can disable this
|
158
|
+
inflection by set to false `add_api_acronym` configuration option.
|
159
|
+
|
160
|
+
## Swagger generation
|
161
|
+
|
162
|
+
Service generator `rails g twirp service` generates swagger file in `public/swagger`
|
163
|
+
by default. You can turn it off or customize path in configuration.
|
164
|
+
|
165
|
+
## Smart service detection
|
166
|
+
|
167
|
+
You can use `rails g twirp svc` if your `Svc` or
|
168
|
+
`SvcAPI` service described at `company/service/subservice/version/etc/svc_api.proto`
|
169
|
+
and you have no other files `svc_api.proto`.
|
170
|
+
|
139
171
|
## Development
|
140
172
|
|
141
173
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/twirp_rails/engine.rb
CHANGED
@@ -29,8 +29,10 @@ module TwirpRails
|
|
29
29
|
end
|
30
30
|
|
31
31
|
initializer 'twirp_rails.add_api_acronym' do
|
32
|
-
|
33
|
-
|
32
|
+
if TwirpRails.configuration.add_api_acronym
|
33
|
+
ActiveSupport::Inflector.inflections(:en) do |inflect|
|
34
|
+
inflect.acronym 'API'
|
35
|
+
end
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
require 'twirp_rails/generators/twirp/protoc_adapter'
|
2
|
+
require 'twirp_rails/generators/twirp/init/init_generator'
|
3
|
+
require 'twirp_rails/generators/twirp/clients/clients_generator'
|
4
|
+
require 'twirp_rails/generators/twirp/twirp_generator'
|
5
|
+
require 'twirp_rails/generators/twirp/twirp_rspec_generator'
|
@@ -5,30 +5,37 @@ module Twirp
|
|
5
5
|
desc 'This generator run protoc generation on each file in the twirp_clients dir'
|
6
6
|
|
7
7
|
def check_requirements
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
protoc.check_requirements do |msg|
|
9
|
+
abort msg
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def rm_old_twirp_files
|
14
|
+
return unless cfg.purge_old_twirp_code
|
15
|
+
|
16
|
+
in_root do
|
17
|
+
removed_files = protoc.rm_old_twirp_files
|
18
|
+
|
19
|
+
if removed_files
|
20
|
+
msg = "#{removed_files.size} twirp and pb files purged from #{dst_path}"
|
21
|
+
say_status :protoc, msg, :green
|
22
|
+
end
|
16
23
|
end
|
17
24
|
end
|
18
25
|
|
19
26
|
def generate_twirp_files
|
20
27
|
in_root do
|
21
|
-
FileUtils.mkdir_p
|
28
|
+
FileUtils.mkdir_p dst_path
|
22
29
|
|
23
|
-
protos_mask = File.join
|
30
|
+
protos_mask = File.join src_path, '**/*.proto'
|
24
31
|
proto_files = Dir.glob protos_mask
|
25
32
|
|
26
33
|
proto_files.each do |file|
|
27
|
-
cmd =
|
34
|
+
cmd = protoc.cmd(file)
|
28
35
|
|
29
36
|
`#{cmd}`
|
30
37
|
|
31
|
-
|
38
|
+
abort "protoc failure: #{cmd}" unless $?.success?
|
32
39
|
end
|
33
40
|
end
|
34
41
|
end
|
@@ -39,13 +46,20 @@ module Twirp
|
|
39
46
|
TwirpRails.configuration
|
40
47
|
end
|
41
48
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
"--plugin=#{TwirpGenerator::TWIRP_PLUGIN_PATH}"
|
49
|
+
def abort(msg)
|
50
|
+
raise Thor::InvocationError, msg
|
51
|
+
end
|
46
52
|
|
47
|
-
|
53
|
+
def protoc
|
54
|
+
@protoc ||= ProtocAdapter.new(src_path, dst_path)
|
48
55
|
end
|
49
56
|
|
57
|
+
def src_path
|
58
|
+
cfg.clients_proto_path
|
59
|
+
end
|
60
|
+
|
61
|
+
def dst_path
|
62
|
+
cfg.clients_twirp_code_path
|
63
|
+
end
|
50
64
|
end
|
51
65
|
end
|
@@ -18,4 +18,11 @@ TwirpRails.configure do |config|
|
|
18
18
|
# set to proc to customize log output
|
19
19
|
# set to false to disable feature
|
20
20
|
# config.log_twirp_calls = true
|
21
|
+
#
|
22
|
+
# Delete all files from x_twirp_code_path
|
23
|
+
# before run protoc on proto files
|
24
|
+
# config.purge_old_twirp_code = true
|
25
|
+
#
|
26
|
+
# Add API acronym to inflector
|
27
|
+
# config.add_api_acronym = true
|
21
28
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class ProtocAdapter
|
2
|
+
attr_reader :src_path, :dst_path, :swagger_out_path
|
3
|
+
|
4
|
+
attr_reader :twirp_plugin_path, :swagger_plugin_path, :protoc_path
|
5
|
+
|
6
|
+
def initialize(src_path, dst_path, swagger_out_path: nil)
|
7
|
+
@src_path = src_path
|
8
|
+
@dst_path = dst_path
|
9
|
+
@swagger_out_path = swagger_out_path
|
10
|
+
|
11
|
+
go_path = ENV.fetch('GOPATH') { File.expand_path('~/go') }
|
12
|
+
go_bin_path = File.join(go_path, 'bin')
|
13
|
+
@twirp_plugin_path = ENV.fetch('TWIRP_PLUGIN_PATH') { File.join(go_bin_path, 'protoc-gen-twirp_ruby') }
|
14
|
+
@swagger_plugin_path = ENV.fetch('SWAGGER_PLUGIN_PATH') { File.join(go_bin_path, 'protoc-gen-twirp_swagger') }
|
15
|
+
@protoc_path = `which protoc`.chomp
|
16
|
+
end
|
17
|
+
|
18
|
+
def rm_old_twirp_files
|
19
|
+
return unless File.exists? dst_path
|
20
|
+
|
21
|
+
remove_mask = File.join dst_path, '**/*_{twirp,pb}.rb'
|
22
|
+
files_to_remove = Dir.glob remove_mask
|
23
|
+
|
24
|
+
return if files_to_remove.empty?
|
25
|
+
|
26
|
+
files_to_remove.each do |file|
|
27
|
+
File.unlink file
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def cmd(files, gen_swagger: false)
|
32
|
+
flags = "--proto_path=#{src_path} " \
|
33
|
+
"--ruby_out=#{dst_path} --twirp_ruby_out=#{dst_path} " \
|
34
|
+
"--plugin=#{twirp_plugin_path}"
|
35
|
+
|
36
|
+
if gen_swagger
|
37
|
+
flags += " --plugin=#{swagger_plugin_path}" \
|
38
|
+
" --twirp_swagger_out=#{swagger_out_path}"
|
39
|
+
end
|
40
|
+
|
41
|
+
"#{protoc_path} #{flags} #{files}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_requirements(check_swagger: false)
|
45
|
+
unless File.exist?(protoc_path)
|
46
|
+
yield 'protoc not found - install protobuf (brew/apt/yum install protobuf)'
|
47
|
+
end
|
48
|
+
|
49
|
+
unless File.exist?(twirp_plugin_path)
|
50
|
+
yield <<~TEXT
|
51
|
+
protoc-gen-twirp_ruby not found - install go (brew install go)
|
52
|
+
and run "go get github.com/twitchtv/twirp-ruby/protoc-gen-twirp_ruby
|
53
|
+
or set TWIRP_PLUGIN_PATH environment variable to right location.
|
54
|
+
TEXT
|
55
|
+
end
|
56
|
+
|
57
|
+
if check_swagger && !File.exist?(swagger_plugin_path)
|
58
|
+
yield <<~TEXT
|
59
|
+
protoc-gen-twirp_swagger not found - install go (brew install go)
|
60
|
+
and run "go get github.com/elliots/protoc-gen-twirp_swagger
|
61
|
+
or set SWAGGER_PLUGIN_PATH environment variable to right location.
|
62
|
+
TEXT
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -6,71 +6,99 @@ class TwirpGenerator < Rails::Generators::NamedBase
|
|
6
6
|
class_option :skip_swagger, type: :boolean, default: false
|
7
7
|
class_option :swagger_out, type: :string, default: nil
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
SWAGGER_PLUGIN_PATH = ENV.fetch('SWAGGER_PLUGIN_PATH') { File.join(GO_BIN_PATH, 'protoc-gen-twirp_swagger') }
|
13
|
-
PROTOC_PATH = `which protoc`.chomp
|
9
|
+
def smart_detect_proto_file_name
|
10
|
+
return if File.exist?(proto_file_name) # dont detect when file exists
|
11
|
+
return if class_path.any? # dont detect when file with path
|
14
12
|
|
15
|
-
def check_requirements
|
16
13
|
in_root do
|
17
|
-
|
14
|
+
[file_name, "#{file_name}_api"].each do |file|
|
15
|
+
mask = File.join src_path, "**/#{file}.proto"
|
16
|
+
matched_files = Dir.glob(mask)
|
17
|
+
|
18
|
+
next if matched_files.empty?
|
19
|
+
|
20
|
+
abort "many proto files matched the #{file_name}: #{matched_files.join(' ')}" if matched_files.size > 1
|
21
|
+
|
22
|
+
matched_file = Pathname.new(matched_files.first).relative_path_from Pathname.new(src_path)
|
23
|
+
matched_file = matched_file.to_s[0..-(matched_file.extname.length + 1)] # remove extension
|
24
|
+
|
25
|
+
@file_path = nil # reset cache
|
26
|
+
|
27
|
+
say_status :detect, "Smart detect #{file_name} as #{matched_file}", :yellow
|
28
|
+
assign_names!(matched_file)
|
29
|
+
break
|
30
|
+
end
|
18
31
|
end
|
32
|
+
end
|
19
33
|
|
20
|
-
|
21
|
-
|
34
|
+
def check_requirements
|
35
|
+
in_root do
|
36
|
+
abort "#{proto_file_name} not found" unless File.exist?(proto_file_name)
|
22
37
|
end
|
23
38
|
|
24
|
-
|
25
|
-
|
26
|
-
protoc-gen-twirp_ruby not found - install go (brew install go)
|
27
|
-
and run "go get github.com/twitchtv/twirp-ruby/protoc-gen-twirp_ruby
|
28
|
-
or set TWIRP_PLUGIN_PATH environment variable to right location.
|
29
|
-
TEXT
|
39
|
+
protoc.check_requirements(check_swagger: gen_swagger?) do |msg|
|
40
|
+
abort msg
|
30
41
|
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def rm_old_twirp_files
|
45
|
+
return unless cfg.purge_old_twirp_code
|
31
46
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
47
|
+
in_root do
|
48
|
+
removed_files = protoc.rm_old_twirp_files
|
49
|
+
|
50
|
+
if removed_files
|
51
|
+
msg = "#{removed_files.size} twirp and pb files purged from #{dst_path}"
|
52
|
+
say_status :protoc, msg, :green
|
53
|
+
end
|
38
54
|
end
|
39
55
|
end
|
40
56
|
|
41
57
|
def generate_twirp_files
|
42
58
|
in_root do
|
43
|
-
FileUtils.mkdir_p
|
59
|
+
FileUtils.mkdir_p dst_path
|
44
60
|
|
45
|
-
protos_mask = File.join
|
61
|
+
protos_mask = File.join src_path, '**/*.proto'
|
46
62
|
proto_files = Dir.glob protos_mask
|
47
63
|
|
64
|
+
protoc_files_count = 0
|
65
|
+
swagger_files_count = 0
|
66
|
+
|
48
67
|
proto_files.each do |file|
|
49
68
|
gen_swagger = gen_swagger? && file =~ %r{/#{file_name}\.proto$}
|
50
69
|
|
51
70
|
FileUtils.mkdir_p swagger_out_path if gen_swagger
|
52
71
|
|
53
|
-
cmd =
|
72
|
+
cmd = protoc.cmd(file, gen_swagger: gen_swagger)
|
73
|
+
|
74
|
+
protoc_files_count += 1
|
75
|
+
swagger_files_count += gen_swagger ? 1 : 0
|
54
76
|
|
55
77
|
`#{cmd}`
|
56
78
|
|
57
|
-
|
79
|
+
abort "protoc failure: #{cmd}" unless $?.success?
|
58
80
|
end
|
81
|
+
|
82
|
+
msg = "#{protoc_files_count} proto files processed, #{swagger_files_count} with swagger"
|
83
|
+
say_status :protoc, msg, :green
|
59
84
|
end
|
60
85
|
end
|
61
86
|
|
62
|
-
PROTO_RPC_REGEXP = /\brpc\s+(\S+)\s*\(\s*(\S+)\s*\)\s*returns\s*\(\s*(\S+)\s*\)/m.freeze
|
63
|
-
|
64
87
|
def create_module_files
|
65
88
|
return if regular_class_path.empty?
|
66
89
|
|
67
90
|
class_path.length.times do |i|
|
68
91
|
current_path = class_path[0..i]
|
69
|
-
|
70
|
-
|
92
|
+
|
93
|
+
create_file File.join('app/rpc', "#{current_path.join('/')}.rb"), <<~RUBY
|
94
|
+
# :nocov:
|
95
|
+
#{module_hier(current_path.map(&:camelize))}# :nocov:
|
96
|
+
RUBY
|
71
97
|
end
|
72
98
|
end
|
73
99
|
|
100
|
+
PROTO_RPC_REGEXP = /\brpc\s+(\S+)\s*\(\s*(\S+)\s*\)\s*returns\s*\(\s*(\S+)\s*\)/m.freeze
|
101
|
+
|
74
102
|
def generate_handler
|
75
103
|
methods = proto_content.scan(PROTO_RPC_REGEXP).map do |method, _arg_type, _result_type|
|
76
104
|
optimize_indentation <<~RUBY, 2
|
@@ -134,17 +162,12 @@ class TwirpGenerator < Rails::Generators::NamedBase
|
|
134
162
|
result_type.split('.').map(&:camelize).join('::')
|
135
163
|
end
|
136
164
|
|
137
|
-
def
|
138
|
-
|
139
|
-
|
140
|
-
"--plugin=#{TWIRP_PLUGIN_PATH}"
|
141
|
-
|
142
|
-
if gen_swagger
|
143
|
-
flags += " --plugin=#{SWAGGER_PLUGIN_PATH}" \
|
144
|
-
" --twirp_swagger_out=#{swagger_out_path}"
|
145
|
-
end
|
165
|
+
def src_path
|
166
|
+
cfg.services_proto_path
|
167
|
+
end
|
146
168
|
|
147
|
-
|
169
|
+
def dst_path
|
170
|
+
cfg.services_twirp_code_path
|
148
171
|
end
|
149
172
|
|
150
173
|
def proto_content
|
@@ -157,7 +180,7 @@ class TwirpGenerator < Rails::Generators::NamedBase
|
|
157
180
|
end
|
158
181
|
|
159
182
|
def proto_file_name
|
160
|
-
File.join
|
183
|
+
File.join src_path, "#{file_path}.proto"
|
161
184
|
end
|
162
185
|
|
163
186
|
def cfg
|
@@ -171,4 +194,12 @@ class TwirpGenerator < Rails::Generators::NamedBase
|
|
171
194
|
def swagger_out_path
|
172
195
|
options[:swagger_out] || cfg.swagger_output_path
|
173
196
|
end
|
197
|
+
|
198
|
+
def abort(msg)
|
199
|
+
raise Thor::InvocationError, msg
|
200
|
+
end
|
201
|
+
|
202
|
+
def protoc
|
203
|
+
@protoc ||= ProtocAdapter.new(src_path, dst_path, swagger_out_path: swagger_out_path)
|
204
|
+
end
|
174
205
|
end
|
data/lib/twirp_rails/version.rb
CHANGED
data/lib/twirp_rails.rb
CHANGED
@@ -2,10 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'twirp_rails/version'
|
4
4
|
require 'twirp_rails/engine'
|
5
|
-
require 'twirp_rails/generators/
|
6
|
-
require 'twirp_rails/generators/twirp/clients/clients_generator'
|
7
|
-
require 'twirp_rails/generators/twirp/twirp_generator'
|
8
|
-
require 'twirp_rails/generators/twirp/twirp_rspec_generator'
|
5
|
+
require 'twirp_rails/generators/generators'
|
9
6
|
require 'twirp_rails/active_record_extension'
|
10
7
|
require 'twirp_rails/log_subscriber'
|
11
8
|
|
@@ -60,6 +57,10 @@ module TwirpRails
|
|
60
57
|
config_param :swagger_output_path, 'public/swagger'
|
61
58
|
|
62
59
|
config_param :log_twirp_calls, true
|
60
|
+
|
61
|
+
config_param :purge_old_twirp_code, true
|
62
|
+
|
63
|
+
config_param :add_api_acronym, true
|
63
64
|
end
|
64
65
|
|
65
66
|
def self.configuration
|
@@ -100,4 +101,22 @@ module TwirpRails
|
|
100
101
|
yield
|
101
102
|
end
|
102
103
|
end
|
104
|
+
|
105
|
+
# Convert google.protobuf.Timestamp or Google::Protobuf::Timestampp hash
|
106
|
+
# to [Time]
|
107
|
+
# @param [Hash|Google::Protobuf::Timestamp] proto_timestamp
|
108
|
+
def self.timestamp_to_time(proto_timestamp)
|
109
|
+
return nil unless proto_timestamp
|
110
|
+
|
111
|
+
proto_timestamp = proto_timestamp.to_h unless proto_timestamp.is_a?(Hash)
|
112
|
+
|
113
|
+
seconds = proto_timestamp[:seconds]
|
114
|
+
raise "invalid timestamp #{proto_timestamp.inspect}" unless seconds
|
115
|
+
|
116
|
+
nanos = proto_timestamp[:nanos]
|
117
|
+
|
118
|
+
seconds += nanos * 1e-9 unless nanos.nil? || nanos.zero?
|
119
|
+
|
120
|
+
Time.zone.at seconds
|
121
|
+
end
|
103
122
|
end
|
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.
|
4
|
+
version: 0.4.1
|
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-
|
11
|
+
date: 2020-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: twirp
|
@@ -142,12 +142,14 @@ 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/generators/generators.rb
|
145
146
|
- lib/twirp_rails/generators/twirp/USAGE
|
146
147
|
- lib/twirp_rails/generators/twirp/clients/USAGE
|
147
148
|
- lib/twirp_rails/generators/twirp/clients/clients_generator.rb
|
148
149
|
- lib/twirp_rails/generators/twirp/init/USAGE
|
149
150
|
- lib/twirp_rails/generators/twirp/init/init_generator.rb
|
150
151
|
- lib/twirp_rails/generators/twirp/init/templates/twirp_rails.rb
|
152
|
+
- lib/twirp_rails/generators/twirp/protoc_adapter.rb
|
151
153
|
- lib/twirp_rails/generators/twirp/twirp_generator.rb
|
152
154
|
- lib/twirp_rails/generators/twirp/twirp_rspec_generator.rb
|
153
155
|
- lib/twirp_rails/log_subscriber.rb
|