runtime_profiler 0.3.0 → 0.3.4

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: 7839cd9d608c73c35a269e4bf7f2f52ae482e714dd99a108e9078e6628f9a86b
4
- data.tar.gz: 9eecf865436dcd07b575d96c1bfb21d1ba1c9344c9100aa955ed00a84d2e8011
3
+ metadata.gz: 4c567a2661f9eec0b394b9751be7e66994e12eea070333f1123ca7c8178e3897
4
+ data.tar.gz: 6eaf3618331b9f5a2c9ea5c657cb61aeb67b391456c4a82f74937a800b78afe7
5
5
  SHA512:
6
- metadata.gz: eaeedf57a5c02b27e1f75778290f821a4b0ed3901220c7dce8529df44d4bf49fe8d0846a4bb3e7e73b485c96196f85d7d57a6cc3e8df93bfda8b05676526ddc1
7
- data.tar.gz: 196e71a0244d7d47c8af6585213c45373dcc8d694bac70daa86e9688877d4b02fc029bc50df87baf3ce288e64c8c7850ea717603975eb38a9da367e34998d9a5
6
+ metadata.gz: 1f5466a9848de8f4e8dbf80e57d48c1dd146f4867ad7b31f8bae7a88a441b562d75c8efbd54c33ced2efc125b1057bdafa571ff94d3c7c5015ce7ae2e73c5847
7
+ data.tar.gz: f53a00037808f40793cc28d523577f405581ed5588b29146c49daabe02151a7ad34b5c205aede70c7c93bc98e8858de08c740a9b675bac3ef22e9c67475dc438
data/README.md CHANGED
@@ -1,16 +1,35 @@
1
- # runtime_profiler - Runtime Profiler for Rails Applications [![Build Status](https://wnuqui.semaphoreci.com/badges/runtime_profiler/branches/master.svg?style=shields)](https://wnuqui.semaphoreci.com/projects/runtime_profiler)
1
+ # runtime_profiler
2
2
 
3
- `runtime_profiler` instruments API endpoints or methods in your Rails application using Rails' `ActiveSupport::Notifications`. Currently, it is intended to be used during development or test.
3
+ *A runtime profiler for Rails applications.*
4
4
 
5
- It then aggregates and generates report to give you insights about specific calls in your Rails application.
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
- ## Installation
7
+ [![Build Status](https://wnuqui.semaphoreci.com/badges/runtime_profiler/branches/master.svg?style=shields)](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
- ## Profiling/Instrumenting
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
- To start profiling, you can make a test that targets a particular endpoint and use `RuntimeProfiler.profile!` method in the test. The output of instrumentation will be generated under the `tmp` folder of your application.
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
- If you prefer writing just code snippet, then just wrap the snippet with `RuntimeProfiler.profile!` method:
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 (tests or not) where `RuntimeProfiler.profile!` is used must be **free from any mocking** since your goal is to check bottlenecks.
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
- ## Viewing Profiling Result
89
+ ### Viewing Profiling Result
50
90
 
51
- To see profiling/instrumenting report, you can open the report in browser with JSON viewer report. Or you can run the following command:
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 ~/the-rails-app/tmp/runtime-profiling-51079-1521371428.json
94
+ bundle exec runtime_profiler view tmp/rp-124094-1608308786.json
55
95
  ```
56
96
 
57
- ### view options
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
- ## Configurations
140
+ ### Configurations
101
141
 
102
- All the configurable variables and their defaults are listed below. These configurations can be put in the `config/initializers` folder of your Rails application.
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]
@@ -11,15 +11,15 @@ module RuntimeProfiler
11
11
  end
12
12
 
13
13
  config_accessor :instrumented_paths do
14
- %w(app lib)
14
+ %w[app lib]
15
15
  end
16
16
 
17
17
  config_accessor :instrumented_sql_commands do
18
- %w(SELECT INSERT UPDATE DELETE)
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
- Rails.application.eager_load! rescue nil
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
@@ -12,6 +12,7 @@ module RuntimeProfiler
12
12
  def call(*args)
13
13
  event = RuntimeProfiler::ProcessActionEvent.new(args: args)
14
14
  return unless event.recordable?
15
+
15
16
  add event
16
17
  end
17
18
 
@@ -26,12 +26,12 @@ module RuntimeProfiler
26
26
 
27
27
  @data[key][:sql] = event.sanitized_sql
28
28
  @data[key][:runtimes] = [
29
- [ event.total_runtime, event.trace.first ]
29
+ [event.total_runtime, event.trace.first]
30
30
  ]
31
31
  end
32
32
 
33
33
  def update(event)
34
- @data[event.key][:runtimes] << [ event.total_runtime, event.trace.first ]
34
+ @data[event.key][:runtimes] << [event.total_runtime, event.trace.first]
35
35
  end
36
36
  end
37
37
  end
@@ -49,4 +49,4 @@ module RuntimeProfiler
49
49
  run!
50
50
  end
51
51
  end
52
- end
52
+ end
@@ -30,4 +30,4 @@ module RuntimeProfiler
30
30
  @key ||= Digest::MD5.hexdigest(path.downcase)
31
31
  end
32
32
  end
33
- end
33
+ end
@@ -8,12 +8,34 @@ module RuntimeProfiler
8
8
  end
9
9
 
10
10
  def persist!
11
- instrumented_api = [
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('#') if controller_data[:payload]
34
+ ].join('#')
35
+ end
15
36
 
16
- instrumentation_data = {
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
- .subscribe('sql.active_record', @active_record_callback)
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
- .subscribe('process_action.action_controller', @action_controller_callback)
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
- self.instrumented_constants.flatten
42
- .each { |constant| MethodMeter.observe(constant) }
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
- controller_data: @action_controller_callback.controller_data,
50
- sql_data: @active_record_callback.data
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( File.read(json_file) )
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
- 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
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)', 'SQL Query', 'Source']
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, query, source]
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
- options.sort_by = 'total_runtime' if options.sort_by == 'max_runtime'
247
- data.sort_by { |d| options.sort_by == 'total_runtime' ? -d['total_runtime'] : -d['total_calls'] }
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
 
@@ -1,3 +1,3 @@
1
1
  module RuntimeProfiler
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.3.4'.freeze
3
3
  end
@@ -1,5 +1,4 @@
1
- # coding: utf-8
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.add_runtime_dependency 'terminal-table'
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 'defined_methods'
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.0
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-04 00:00:00.000000000 Z
11
+ date: 2020-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
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: '0'
26
+ version: 3.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 12.3.3
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: 12.3.3
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: activesupport
56
+ name: minitest-line
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 3.0.0
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: 3.0.0
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: minitest-line
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: terminal-table
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: commander
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: defined_methods
168
+ name: terminal-table
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
171
  - - ">="