runtime_profiler 0.3.0 → 0.3.4
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/README.md +56 -16
- data/lib/runtime_profiler.rb +9 -5
- data/lib/runtime_profiler/callbacks/action_controller.rb +1 -0
- data/lib/runtime_profiler/callbacks/active_record.rb +2 -2
- data/lib/runtime_profiler/cli.rb +1 -1
- data/lib/runtime_profiler/events/process_action_event.rb +1 -1
- data/lib/runtime_profiler/instrumentation_data.rb +25 -26
- data/lib/runtime_profiler/profiler.rb +7 -7
- data/lib/runtime_profiler/text_report.rb +16 -17
- data/lib/runtime_profiler/version.rb +1 -1
- data/runtime_profiler.gemspec +7 -7
- metadata +29 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c567a2661f9eec0b394b9751be7e66994e12eea070333f1123ca7c8178e3897
|
4
|
+
data.tar.gz: 6eaf3618331b9f5a2c9ea5c657cb61aeb67b391456c4a82f74937a800b78afe7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f5466a9848de8f4e8dbf80e57d48c1dd146f4867ad7b31f8bae7a88a441b562d75c8efbd54c33ced2efc125b1057bdafa571ff94d3c7c5015ce7ae2e73c5847
|
7
|
+
data.tar.gz: f53a00037808f40793cc28d523577f405581ed5588b29146c49daabe02151a7ad34b5c205aede70c7c93bc98e8858de08c740a9b675bac3ef22e9c67475dc438
|
data/README.md
CHANGED
@@ -1,16 +1,35 @@
|
|
1
|
-
# runtime_profiler
|
1
|
+
# runtime_profiler
|
2
2
|
|
3
|
-
|
3
|
+
*A runtime profiler for Rails applications.*
|
4
4
|
|
5
|
-
|
5
|
+
Check which part of your Rails application is causing slow response time. **runtime_profiler** gives you an easy way to find performance problems by profiling an endpoint or a method in your Rails application.
|
6
6
|
|
7
|
-
|
7
|
+
[](https://wnuqui.semaphoreci.com/projects/runtime_profiler)
|
8
|
+
|
9
|
+
## Table of contents
|
10
|
+
|
11
|
+
- [Getting Started](#getting-started)
|
12
|
+
- [Installing](#installing)
|
13
|
+
- [Profiling](#profiling)
|
14
|
+
- [Structure](#structure)
|
15
|
+
- [Examples](#examples)
|
16
|
+
- [Viewing Profiling Result](#viewing-profiling-result)
|
17
|
+
- [view Options](#view-options)
|
18
|
+
- [Configurations](#configurations)
|
19
|
+
- [Development](#development)
|
20
|
+
- [Contributing](#contributing)
|
21
|
+
- [Acknowledgement](#acknowledgement)
|
22
|
+
- [License](#license)
|
23
|
+
|
24
|
+
## Getting Started
|
25
|
+
|
26
|
+
### Installing
|
8
27
|
|
9
28
|
Add this line to your application's Gemfile:
|
10
29
|
|
11
30
|
```ruby
|
31
|
+
# In your Gemfile
|
12
32
|
group :development, :test do
|
13
|
-
... ...
|
14
33
|
gem 'runtime_profiler'
|
15
34
|
end
|
16
35
|
```
|
@@ -19,13 +38,33 @@ And then execute:
|
|
19
38
|
|
20
39
|
$ bundle
|
21
40
|
|
22
|
-
|
41
|
+
Or install it yourself as:
|
42
|
+
|
43
|
+
$ gem install runtime_profiler
|
44
|
+
|
45
|
+
### Profiling
|
46
|
+
|
47
|
+
#### Structure
|
48
|
+
|
49
|
+
To profile a specific class (model, controller, etc), all you need to do is to wrap a line where the target class (or instance) is calling a method (entry point of profiling).
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
# Profiles runtime of `ClassToProfile` class.
|
53
|
+
RuntimeProfiler.profile!('description', [ClassToProfile]) {
|
54
|
+
# one line where `ClassToProfile` (or its instance) is calling a method
|
55
|
+
}
|
56
|
+
```
|
57
|
+
|
58
|
+
Since the second argument of `.profile!` accepts array of classes, then you can provide all target classes that you want to profile.
|
59
|
+
|
60
|
+
#### Examples
|
23
61
|
|
24
|
-
|
62
|
+
You can make a test that targets a particular endpoint (or even just a method) and use `RuntimeProfiler.profile!` method in the test.
|
25
63
|
|
26
|
-
Example of a test code wrap by `RuntimeProfiler.profile!` method:
|
27
64
|
```ruby
|
28
65
|
it 'updates user' do
|
66
|
+
# Profiles runtime of PUT /users/:id endpoint and
|
67
|
+
# specifically interested with the methods of `User` model.
|
29
68
|
RuntimeProfiler.profile!('updates user', [User]) {
|
30
69
|
patch :update, { id: user.id, name: 'Joe' }
|
31
70
|
}
|
@@ -36,25 +75,26 @@ end
|
|
36
75
|
|
37
76
|
Run the test as usual and follow printed instructions after running.
|
38
77
|
|
39
|
-
|
78
|
+
Or if you prefer writing just code snippet, then just wrap the snippet with `RuntimeProfiler.profile!` method:
|
40
79
|
```ruby
|
80
|
+
# Profiles runtime of `UserMailer` mailer.
|
41
81
|
RuntimeProfiler.profile!('UserMailer', [UserMailer]) {
|
42
82
|
user = User.last
|
43
83
|
UserMailer.with(user: user).weekly_summary.deliver_now
|
44
84
|
}
|
45
85
|
```
|
46
86
|
|
47
|
-
**Note:** The code (
|
87
|
+
**Note:** The code (test or not) where `RuntimeProfiler.profile!` is used must be **free from any mocking/stubbing** since the goal is to check performance bottlenecks.
|
48
88
|
|
49
|
-
|
89
|
+
### Viewing Profiling Result
|
50
90
|
|
51
|
-
To see profiling
|
91
|
+
To see profiling report, you can open the report in browser with JSON viewer report. Or you can run the following command:
|
52
92
|
|
53
93
|
```bash
|
54
|
-
bundle exec runtime_profiler view
|
94
|
+
bundle exec runtime_profiler view tmp/rp-124094-1608308786.json
|
55
95
|
```
|
56
96
|
|
57
|
-
|
97
|
+
#### view options
|
58
98
|
|
59
99
|
Here are the command line options for `runtime_profiler view` command.
|
60
100
|
|
@@ -97,9 +137,9 @@ $ bundle exec runtime_profiler view --help
|
|
97
137
|
ROUNDING is integer value. Used in rounding runtimes. Default is 4.
|
98
138
|
```
|
99
139
|
|
100
|
-
|
140
|
+
### Configurations
|
101
141
|
|
102
|
-
All the configurable variables and their defaults are listed below.
|
142
|
+
All the configurable variables and their defaults are listed below. There is no one correct place where to put these configurations. It can be inside `config/initializers` folder of your Rails application. Or if you are using test to profile, it can be in the last part of `spec/spec_helper.rb`.
|
103
143
|
```ruby
|
104
144
|
RuntimeProfiler.output_path = File.join(Rails.root.to_s, 'tmp')
|
105
145
|
RuntimeProfiler.instrumented_constants = [User]
|
data/lib/runtime_profiler.rb
CHANGED
@@ -11,15 +11,15 @@ module RuntimeProfiler
|
|
11
11
|
end
|
12
12
|
|
13
13
|
config_accessor :instrumented_paths do
|
14
|
-
%w
|
14
|
+
%w[app lib]
|
15
15
|
end
|
16
16
|
|
17
17
|
config_accessor :instrumented_sql_commands do
|
18
|
-
%w
|
18
|
+
%w[SELECT INSERT UPDATE DELETE]
|
19
19
|
end
|
20
20
|
|
21
21
|
config_accessor :output_path do
|
22
|
-
if defined?(Rails) && Rails.respond_to?(:root)
|
22
|
+
if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
|
23
23
|
File.join(Rails.root.to_s, 'tmp')
|
24
24
|
else
|
25
25
|
'tmp'
|
@@ -28,7 +28,11 @@ module RuntimeProfiler
|
|
28
28
|
|
29
29
|
class << self
|
30
30
|
def configure
|
31
|
-
|
31
|
+
begin
|
32
|
+
Rails.application.eager_load!
|
33
|
+
rescue StandardError
|
34
|
+
nil
|
35
|
+
end
|
32
36
|
yield self if block_given?
|
33
37
|
end
|
34
38
|
|
@@ -42,4 +46,4 @@ module RuntimeProfiler
|
|
42
46
|
profiler.save_instrumentation_data
|
43
47
|
end
|
44
48
|
end
|
45
|
-
end
|
49
|
+
end
|
@@ -26,12 +26,12 @@ module RuntimeProfiler
|
|
26
26
|
|
27
27
|
@data[key][:sql] = event.sanitized_sql
|
28
28
|
@data[key][:runtimes] = [
|
29
|
-
[
|
29
|
+
[event.total_runtime, event.trace.first]
|
30
30
|
]
|
31
31
|
end
|
32
32
|
|
33
33
|
def update(event)
|
34
|
-
@data[event.key][:runtimes] << [
|
34
|
+
@data[event.key][:runtimes] << [event.total_runtime, event.trace.first]
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
data/lib/runtime_profiler/cli.rb
CHANGED
@@ -8,12 +8,34 @@ module RuntimeProfiler
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def persist!
|
11
|
-
|
11
|
+
File.open(output_file, 'w') do |f|
|
12
|
+
f.write JSON.dump(instrumentation_data)
|
13
|
+
end
|
14
|
+
|
15
|
+
puts "\n"
|
16
|
+
puts 'Profiling data written at ' + output_file.to_s
|
17
|
+
puts 'You can view profiling data via: bundle exec runtime_profiler view ' + output_file.to_s
|
18
|
+
puts "\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def output_file
|
24
|
+
FileUtils.mkdir_p(RuntimeProfiler.output_path)
|
25
|
+
filename = ['rp', Process.pid, Time.now.to_i].join('-') + '.json'
|
26
|
+
File.join(RuntimeProfiler.output_path, filename)
|
27
|
+
end
|
28
|
+
|
29
|
+
def instrumented_api
|
30
|
+
return unless controller_data[:payload]
|
31
|
+
@instrumented_api ||= [
|
12
32
|
controller_data[:payload][:controller],
|
13
33
|
controller_data[:payload][:action]
|
14
|
-
].join('#')
|
34
|
+
].join('#')
|
35
|
+
end
|
15
36
|
|
16
|
-
|
37
|
+
def instrumentation_data
|
38
|
+
@instrumentation_data ||= {
|
17
39
|
instrumentation: {
|
18
40
|
instrumented_api: instrumented_api,
|
19
41
|
summary: {
|
@@ -32,31 +54,8 @@ module RuntimeProfiler
|
|
32
54
|
instrumented_at: Time.now
|
33
55
|
}
|
34
56
|
}
|
35
|
-
|
36
|
-
FileUtils.mkdir_p(RuntimeProfiler.output_path)
|
37
|
-
filename = ['runtime-profiling', Process.pid, Time.now.to_i].join('-') << '.json'
|
38
|
-
output_file = File.join(RuntimeProfiler.output_path, filename)
|
39
|
-
|
40
|
-
File.open(output_file, 'w') do |f|
|
41
|
-
f.write JSON.dump(instrumentation_data)
|
42
|
-
end
|
43
|
-
|
44
|
-
puts "\n"
|
45
|
-
puts '~~~~> [ Profiling RUNTIME ] Profiling now COMPLETE and JSON report is written at ' + output_file.to_s
|
46
|
-
puts '~~~~> [ Profiling RUNTIME ]'
|
47
|
-
puts '~~~~> [ Profiling RUNTIME ] You can do the following to view the JSON report in console:'
|
48
|
-
puts '~~~~> [ Profiling RUNTIME ]'
|
49
|
-
puts '~~~~> [ Profiling RUNTIME ] bundle exec runtime_profiler view ' + output_file.to_s
|
50
|
-
puts '~~~~> [ Profiling RUNTIME ]'
|
51
|
-
puts '~~~~> [ Profiling RUNTIME ] Or'
|
52
|
-
puts '~~~~> [ Profiling RUNTIME ]'
|
53
|
-
puts '~~~~> [ Profiling RUNTIME ] bundle exec runtime_profiler view --help'
|
54
|
-
puts '~~~~> [ Profiling RUNTIME ]'
|
55
|
-
puts '~~~~> [ Profiling RUNTIME ] for more details.'
|
56
57
|
end
|
57
58
|
|
58
|
-
private
|
59
|
-
|
60
59
|
def method_calls_data
|
61
60
|
@method_calls_data ||= begin
|
62
61
|
instrumented_methods = {}
|
@@ -23,12 +23,12 @@ module RuntimeProfiler
|
|
23
23
|
@active_record_callback = Callback::ActiveRecord.new
|
24
24
|
|
25
25
|
@subscribers << ActiveSupport::Notifications
|
26
|
-
|
26
|
+
.subscribe('sql.active_record', @active_record_callback)
|
27
27
|
|
28
28
|
@action_controller_callback = Callback::ActionController.new
|
29
29
|
|
30
30
|
@subscribers << ActiveSupport::Notifications
|
31
|
-
|
31
|
+
.subscribe('process_action.action_controller', @action_controller_callback)
|
32
32
|
end
|
33
33
|
|
34
34
|
def unsubscribe_to_event_notifications
|
@@ -38,18 +38,18 @@ module RuntimeProfiler
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def prepare_methods_to_instrument
|
41
|
-
|
42
|
-
|
41
|
+
instrumented_constants.flatten
|
42
|
+
.each { |constant| MethodMeter.observe(constant) }
|
43
43
|
end
|
44
44
|
|
45
45
|
def save_instrumentation_data
|
46
46
|
unsubscribe_to_event_notifications
|
47
47
|
|
48
48
|
instrumentation_data = RuntimeProfiler::InstrumentationData.new \
|
49
|
-
|
50
|
-
|
49
|
+
controller_data: @action_controller_callback.controller_data,
|
50
|
+
sql_data: @active_record_callback.data
|
51
51
|
|
52
52
|
instrumentation_data.persist!
|
53
53
|
end
|
54
54
|
end
|
55
|
-
end
|
55
|
+
end
|
@@ -26,12 +26,12 @@ module RuntimeProfiler
|
|
26
26
|
\e[1mSQL CALLS\e[22m
|
27
27
|
Total : %s
|
28
28
|
Total Unique : %s
|
29
|
-
|
29
|
+
|
30
30
|
\e[1mSLOWEST\e[22m
|
31
31
|
Total Runtime : %s ms
|
32
32
|
SQL : %s
|
33
33
|
Source : %s
|
34
|
-
|
34
|
+
|
35
35
|
\e[1mMOSTLY CALLED\e[22m
|
36
36
|
Total Calls : %s
|
37
37
|
Total Runtime : %s ms
|
@@ -86,7 +86,7 @@ module RuntimeProfiler
|
|
86
86
|
attr_accessor :data, :options
|
87
87
|
|
88
88
|
def initialize(json_file, options)
|
89
|
-
self.data = JSON.parse(
|
89
|
+
self.data = JSON.parse(File.read(json_file))
|
90
90
|
self.options = options
|
91
91
|
end
|
92
92
|
|
@@ -121,12 +121,12 @@ module RuntimeProfiler
|
|
121
121
|
|
122
122
|
def print_summary
|
123
123
|
summary = if only_methods?
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
124
|
+
METHODS_DETAILS_TEMPLATE % details_template_data
|
125
|
+
elsif only_sqls?
|
126
|
+
SQLS_DETAILS_TEMPLATE % details_template_data
|
127
|
+
else
|
128
|
+
FULL_DETAILS_TEMPLATE % details_template_data
|
129
|
+
end
|
130
130
|
puts summary
|
131
131
|
end
|
132
132
|
|
@@ -158,7 +158,6 @@ module RuntimeProfiler
|
|
158
158
|
]
|
159
159
|
t.add_separator if index < instrumented_methods.size - 1
|
160
160
|
end
|
161
|
-
|
162
161
|
end
|
163
162
|
|
164
163
|
puts
|
@@ -176,7 +175,7 @@ module RuntimeProfiler
|
|
176
175
|
instrumented_sql_calls = sort(instrumented_sql_calls, false)
|
177
176
|
|
178
177
|
table = Terminal::Table.new do |t|
|
179
|
-
t.headings = ['Count', 'Total Runtime (ms)', 'Average Runtime (ms)', '
|
178
|
+
t.headings = ['SQL Query', 'Count', 'Total Runtime (ms)', 'Average Runtime (ms)', 'Source']
|
180
179
|
|
181
180
|
instrumented_sql_calls.each_with_index do |row, index|
|
182
181
|
chopped_sql = wrap_text(row['sql'], sql_width)
|
@@ -192,18 +191,17 @@ module RuntimeProfiler
|
|
192
191
|
(0...total_lines).each do |line|
|
193
192
|
count = line == 0 ? row['total_calls'] : ''
|
194
193
|
average = line == 0 ? average_runtime : ''
|
195
|
-
total_runtime = line == 0 ? total_runtime
|
194
|
+
total_runtime = line == 0 ? total_runtime : ''
|
196
195
|
source = source_list.length > line ? source_list[line] : ''
|
197
196
|
query = row['sql'].length > line ? chopped_sql[line] : ''
|
198
197
|
|
199
198
|
t.add_row []
|
200
|
-
t.add_row [count, total_runtime, average,
|
199
|
+
t.add_row [query, count, total_runtime, average, source]
|
201
200
|
end
|
202
201
|
|
203
202
|
t.add_row []
|
204
203
|
t.add_separator if index < instrumented_sql_calls.size - 1
|
205
204
|
end
|
206
|
-
|
207
205
|
end
|
208
206
|
|
209
207
|
puts
|
@@ -215,6 +213,7 @@ module RuntimeProfiler
|
|
215
213
|
|
216
214
|
def wrap_text(text, width)
|
217
215
|
return [text] if text.length <= width
|
216
|
+
|
218
217
|
text.scan(/.{1,#{width}}/)
|
219
218
|
end
|
220
219
|
|
@@ -231,7 +230,7 @@ module RuntimeProfiler
|
|
231
230
|
end
|
232
231
|
end
|
233
232
|
|
234
|
-
def sort(data, methods=true)
|
233
|
+
def sort(data, methods = true)
|
235
234
|
if methods
|
236
235
|
data.sort_by do |d|
|
237
236
|
if options.sort_by == 'max_runtime'
|
@@ -243,8 +242,8 @@ module RuntimeProfiler
|
|
243
242
|
end
|
244
243
|
end
|
245
244
|
else
|
246
|
-
|
247
|
-
data.sort_by { |d| options.sort_by == 'total_runtime' ?
|
245
|
+
options.sort_by = 'total_runtime' if options.sort_by == 'max_runtime'
|
246
|
+
data.sort_by { |d| options.sort_by == 'total_runtime' ? -d['total_runtime'] : -d['total_calls'] }
|
248
247
|
end
|
249
248
|
end
|
250
249
|
|
data/runtime_profiler.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'runtime_profiler/version'
|
5
4
|
|
@@ -19,15 +18,16 @@ Gem::Specification.new do |spec|
|
|
19
18
|
spec.executables = ['runtime_profiler']
|
20
19
|
spec.require_paths = ['lib']
|
21
20
|
|
21
|
+
spec.add_development_dependency 'activesupport', '>= 3.0.0'
|
22
22
|
spec.add_development_dependency 'bundler'
|
23
|
-
spec.add_development_dependency 'rake', '>= 12.3.3'
|
24
23
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
25
|
-
spec.add_development_dependency 'activesupport', '>= 3.0.0'
|
26
|
-
spec.add_development_dependency 'pry'
|
27
24
|
spec.add_development_dependency 'minitest-line'
|
28
|
-
spec.
|
25
|
+
spec.add_development_dependency 'pry'
|
26
|
+
spec.add_development_dependency 'rake', '>= 12.3.3'
|
27
|
+
spec.add_development_dependency 'rubocop'
|
29
28
|
spec.add_runtime_dependency 'commander'
|
29
|
+
spec.add_runtime_dependency 'defined_methods'
|
30
30
|
spec.add_runtime_dependency 'hirb'
|
31
31
|
spec.add_runtime_dependency 'method_meter'
|
32
|
-
spec.add_runtime_dependency '
|
32
|
+
spec.add_runtime_dependency 'terminal-table'
|
33
33
|
end
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: runtime_profiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wilfrido T. Nuqui Jr.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.0.0
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 3.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,19 +53,19 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: minitest-line
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '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:
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pry
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,7 +81,21 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 12.3.3
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 12.3.3
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - ">="
|
@@ -95,7 +109,7 @@ dependencies:
|
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: commander
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
@@ -109,7 +123,7 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: defined_methods
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - ">="
|
@@ -151,7 +165,7 @@ dependencies:
|
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
168
|
+
name: terminal-table
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
156
170
|
requirements:
|
157
171
|
- - ">="
|