string_to_number 0.2.0 → 0.3.0

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.
data/microbenchmark.rb CHANGED
@@ -9,10 +9,10 @@ require 'benchmark'
9
9
 
10
10
  class MicroBenchmark
11
11
  def self.run
12
- puts "StringToNumber Micro-Benchmarks"
13
- puts "=" * 50
12
+ puts 'StringToNumber Micro-Benchmarks'
13
+ puts '=' * 50
14
14
  puts
15
-
15
+
16
16
  # Test individual components
17
17
  test_initialization
18
18
  test_regex_compilation
@@ -20,43 +20,45 @@ class MicroBenchmark
20
20
  test_hash_lookups
21
21
  test_string_operations
22
22
  test_recursion_overhead
23
-
23
+
24
24
  puts "\nConclusions and Recommendations:"
25
- puts "=" * 50
25
+ puts '=' * 50
26
26
  analyze_results
27
27
  end
28
28
 
29
29
  def self.test_initialization
30
- puts "1. Initialization Performance"
31
- puts "-" * 30
32
-
30
+ puts '1. Initialization Performance'
31
+ puts '-' * 30
32
+
33
33
  # Test the cost of creating new instances
34
34
  sentences = ['un', 'vingt et un', 'mille deux cent', 'trois milliards cinq cents millions']
35
-
35
+
36
36
  sentences.each do |sentence|
37
37
  time = Benchmark.realtime do
38
38
  1000.times { StringToNumber::ToNumber.new(sentence) }
39
39
  end
40
-
40
+
41
41
  puts "#{sentence.ljust(35)}: #{(time * 1000).round(4)}ms per 1000 instances"
42
42
  end
43
43
  puts
44
44
  end
45
45
 
46
46
  def self.test_regex_compilation
47
- puts "2. Regex Compilation Performance"
48
- puts "-" * 30
49
-
47
+ puts '2. Regex Compilation Performance'
48
+ puts '-' * 30
49
+
50
50
  # Test the cost of regex compilation vs pre-compiled regex
51
- keys = StringToNumber::ToNumber::POWERS_OF_TEN.keys.reject { |k| %w[un dix].include?(k) }.sort_by(&:length).reverse.join('|')
52
-
51
+ keys = StringToNumber::ToNumber::POWERS_OF_TEN.keys.reject do |k|
52
+ %w[un dix].include?(k)
53
+ end.sort_by(&:length).reverse.join('|')
54
+
53
55
  # Dynamic compilation
54
56
  dynamic_time = Benchmark.realtime do
55
57
  1000.times do
56
58
  /(?<f>.*?)\s?(?<m>#{keys})/.match('trois milliards')
57
59
  end
58
60
  end
59
-
61
+
60
62
  # Pre-compiled regex
61
63
  compiled_regex = /(?<f>.*?)\s?(?<m>#{Regexp.escape(keys)})/
62
64
  precompiled_time = Benchmark.realtime do
@@ -64,7 +66,7 @@ class MicroBenchmark
64
66
  compiled_regex.match('trois milliards')
65
67
  end
66
68
  end
67
-
69
+
68
70
  puts "Dynamic regex compilation: #{(dynamic_time * 1000).round(4)}ms per 1000 matches"
69
71
  puts "Pre-compiled regex: #{(precompiled_time * 1000).round(4)}ms per 1000 matches"
70
72
  puts "Compilation overhead: #{((dynamic_time - precompiled_time) * 1000).round(4)}ms per 1000 matches"
@@ -72,62 +74,64 @@ class MicroBenchmark
72
74
  end
73
75
 
74
76
  def self.test_regex_matching
75
- puts "3. Regex Pattern Complexity"
76
- puts "-" * 30
77
-
77
+ puts '3. Regex Pattern Complexity'
78
+ puts '-' * 30
79
+
78
80
  # Test different regex patterns to see which are expensive
79
81
  test_patterns = {
80
82
  'Simple word match' => /vingt/,
81
83
  'Word boundary match' => /\bvingt\b/,
82
84
  'Named capture groups' => /(?<f>.*?)\s?(?<m>vingt)/,
83
85
  'Complex alternation' => /(?<f>.*?)\s?(?<m>vingt|trente|quarante|cinquante)/,
84
- 'Full keys pattern' => /(?<f>.*?)\s?(?<m>#{StringToNumber::ToNumber::POWERS_OF_TEN.keys.reject { |k| %w[un dix].include?(k) }.sort_by(&:length).reverse.join('|')})/
86
+ 'Full keys pattern' => /(?<f>.*?)\s?(?<m>#{StringToNumber::ToNumber::POWERS_OF_TEN.keys.reject do |k|
87
+ %w[un dix].include?(k)
88
+ end.sort_by(&:length).reverse.join('|')})/
85
89
  }
86
-
90
+
87
91
  test_string = 'trois milliards cinq cents millions'
88
-
92
+
89
93
  test_patterns.each do |name, pattern|
90
94
  time = Benchmark.realtime do
91
95
  5000.times { pattern.match(test_string) }
92
96
  end
93
-
97
+
94
98
  puts "#{name.ljust(25)}: #{(time * 1000).round(4)}ms per 5000 matches"
95
99
  end
96
100
  puts
97
101
  end
98
102
 
99
103
  def self.test_hash_lookups
100
- puts "4. Hash Lookup Performance"
101
- puts "-" * 30
102
-
104
+ puts '4. Hash Lookup Performance'
105
+ puts '-' * 30
106
+
103
107
  exceptions = StringToNumber::ToNumber::EXCEPTIONS
104
108
  powers = StringToNumber::ToNumber::POWERS_OF_TEN
105
-
109
+
106
110
  # Test lookup performance
107
111
  exceptions_time = Benchmark.realtime do
108
- 10000.times do
112
+ 10_000.times do
109
113
  exceptions['vingt']
110
114
  exceptions['trois']
111
115
  exceptions['cent']
112
116
  end
113
117
  end
114
-
118
+
115
119
  powers_time = Benchmark.realtime do
116
- 10000.times do
120
+ 10_000.times do
117
121
  powers['million']
118
122
  powers['mille']
119
123
  powers['cent']
120
124
  end
121
125
  end
122
-
126
+
123
127
  # Test nil checks
124
128
  nil_check_time = Benchmark.realtime do
125
- 10000.times do
129
+ 10_000.times do
126
130
  exceptions['nonexistent'].nil?
127
131
  powers['nonexistent'].nil?
128
132
  end
129
133
  end
130
-
134
+
131
135
  puts "EXCEPTIONS hash lookups: #{(exceptions_time * 100).round(4)}ms per 10000 lookups"
132
136
  puts "POWERS_OF_TEN hash lookups: #{(powers_time * 100).round(4)}ms per 10000 lookups"
133
137
  puts "Nil check operations: #{(nil_check_time * 100).round(4)}ms per 10000 checks"
@@ -135,28 +139,28 @@ class MicroBenchmark
135
139
  end
136
140
 
137
141
  def self.test_string_operations
138
- puts "5. String Operations Performance"
139
- puts "-" * 30
140
-
142
+ puts '5. String Operations Performance'
143
+ puts '-' * 30
144
+
141
145
  test_string = 'TROIS MILLIARDS CINQ CENTS MILLIONS'
142
-
146
+
143
147
  # Test different string operations
144
148
  downcase_time = Benchmark.realtime do
145
149
  5000.times { test_string.downcase }
146
150
  end
147
-
151
+
148
152
  gsub_time = Benchmark.realtime do
149
- 5000.times { test_string.gsub(/MILLIONS/, '') }
153
+ 5000.times { test_string.gsub('MILLIONS', '') }
150
154
  end
151
-
155
+
152
156
  split_time = Benchmark.realtime do
153
- 5000.times { test_string.split(' ') }
157
+ 5000.times { test_string.split }
154
158
  end
155
-
159
+
156
160
  tr_time = Benchmark.realtime do
157
161
  5000.times { test_string.tr('-', ' ') }
158
162
  end
159
-
163
+
160
164
  puts "String#downcase: #{(downcase_time * 1000).round(4)}ms per 5000 operations"
161
165
  puts "String#gsub: #{(gsub_time * 1000).round(4)}ms per 5000 operations"
162
166
  puts "String#split: #{(split_time * 1000).round(4)}ms per 5000 operations"
@@ -165,29 +169,28 @@ class MicroBenchmark
165
169
  end
166
170
 
167
171
  def self.test_recursion_overhead
168
- puts "6. Recursion vs Iteration Performance"
169
- puts "-" * 30
170
-
172
+ puts '6. Recursion vs Iteration Performance'
173
+ puts '-' * 30
174
+
171
175
  # Compare recursive vs iterative approaches
172
- def self.recursive_sum(arr, index = 0)
176
+ recursive_sum = lambda do |arr, index = 0|
173
177
  return 0 if index >= arr.length
174
- arr[index] + recursive_sum(arr, index + 1)
175
- end
176
-
177
- def self.iterative_sum(arr)
178
- arr.sum
178
+
179
+ arr[index] + recursive_sum.call(arr, index + 1)
179
180
  end
180
-
181
+
182
+ iterative_sum = :sum.to_proc
183
+
181
184
  test_array = Array.new(100) { rand(100) }
182
-
185
+
183
186
  recursive_time = Benchmark.realtime do
184
- 1000.times { recursive_sum(test_array) }
187
+ 1000.times { recursive_sum.call(test_array) }
185
188
  end
186
-
189
+
187
190
  iterative_time = Benchmark.realtime do
188
- 1000.times { iterative_sum(test_array) }
191
+ 1000.times { iterative_sum.call(test_array) }
189
192
  end
190
-
193
+
191
194
  puts "Recursive approach: #{(recursive_time * 1000).round(4)}ms per 1000 operations"
192
195
  puts "Iterative approach: #{(iterative_time * 1000).round(4)}ms per 1000 operations"
193
196
  puts "Recursion overhead: #{((recursive_time - iterative_time) * 1000).round(4)}ms per 1000 operations"
@@ -195,32 +198,30 @@ class MicroBenchmark
195
198
  end
196
199
 
197
200
  def self.analyze_results
198
- puts "Key Performance Insights:"
201
+ puts 'Key Performance Insights:'
199
202
  puts
200
- puts "1. 🔍 INITIALIZATION COST:"
201
- puts " - Creating new ToNumber instances is expensive (~13ms per 1000)"
202
- puts " - Consider caching or singleton pattern for repeated use"
203
+ puts '1. 🔍 INITIALIZATION COST:'
204
+ puts ' - Creating new ToNumber instances is expensive (~13ms per 1000)'
205
+ puts ' - Consider caching or singleton pattern for repeated use'
203
206
  puts
204
- puts "2. 🔍 REGEX COMPLEXITY:"
205
- puts " - Complex alternation patterns are the main bottleneck"
206
- puts " - Keys pattern is 521 characters long - very expensive to match"
207
- puts " - Consider breaking down into simpler patterns or using different approach"
207
+ puts '2. 🔍 REGEX COMPLEXITY:'
208
+ puts ' - Complex alternation patterns are the main bottleneck'
209
+ puts ' - Keys pattern is 521 characters long - very expensive to match'
210
+ puts ' - Consider breaking down into simpler patterns or using different approach'
208
211
  puts
209
- puts "3. 🔍 SCALABILITY ISSUES:"
210
- puts " - Performance degrades significantly with input length (43x for longest)"
211
- puts " - Recursive parsing creates overhead for complex numbers"
212
- puts " - String operations add up with multiple passes"
212
+ puts '3. 🔍 SCALABILITY ISSUES:'
213
+ puts ' - Performance degrades significantly with input length (43x for longest)'
214
+ puts ' - Recursive parsing creates overhead for complex numbers'
215
+ puts ' - String operations add up with multiple passes'
213
216
  puts
214
- puts "📊 OPTIMIZATION RECOMMENDATIONS:"
215
- puts " 1. Pre-compile regex patterns in class constants"
216
- puts " 2. Use simpler regex patterns with multiple passes if needed"
217
- puts " 3. Implement caching for repeated conversions"
218
- puts " 4. Consider iterative parsing instead of recursive for complex cases"
219
- puts " 5. Optimize string operations (minimize downcase/gsub calls)"
217
+ puts '📊 OPTIMIZATION RECOMMENDATIONS:'
218
+ puts ' 1. Pre-compile regex patterns in class constants'
219
+ puts ' 2. Use simpler regex patterns with multiple passes if needed'
220
+ puts ' 3. Implement caching for repeated conversions'
221
+ puts ' 4. Consider iterative parsing instead of recursive for complex cases'
222
+ puts ' 5. Optimize string operations (minimize downcase/gsub calls)'
220
223
  end
221
224
  end
222
225
 
223
226
  # Run the micro-benchmarks
224
- if __FILE__ == $0
225
- MicroBenchmark.run
226
- end
227
+ MicroBenchmark.run if __FILE__ == $PROGRAM_NAME
@@ -16,20 +16,20 @@ class PerformanceComparison
16
16
  ].freeze
17
17
 
18
18
  def self.run_comparison
19
- puts "StringToNumber Performance Comparison"
20
- puts "=" * 60
21
- puts "Original vs Optimized Implementation"
22
- puts "=" * 60
19
+ puts 'StringToNumber Performance Comparison'
20
+ puts '=' * 60
21
+ puts 'Original vs Optimized Implementation'
22
+ puts '=' * 60
23
23
  puts
24
24
 
25
25
  TEST_CASES.each_with_index do |test_case, index|
26
26
  puts "Test #{index + 1}: '#{test_case}'"
27
- puts "-" * 50
27
+ puts '-' * 50
28
28
 
29
29
  # Verify both implementations produce same results
30
30
  original_result = StringToNumber.in_numbers(test_case, use_optimized: false)
31
31
  optimized_result = StringToNumber.in_numbers(test_case, use_optimized: true)
32
-
32
+
33
33
  if original_result == optimized_result
34
34
  puts "✅ Results match: #{original_result}"
35
35
  else
@@ -38,7 +38,7 @@ class PerformanceComparison
38
38
  end
39
39
 
40
40
  # Benchmark both implementations
41
- iterations = 10000
41
+ iterations = 10_000
42
42
 
43
43
  original_time = Benchmark.realtime do
44
44
  iterations.times { StringToNumber.in_numbers(test_case, use_optimized: false) }
@@ -55,27 +55,27 @@ class PerformanceComparison
55
55
  puts "Original: #{original_avg.round(4)}ms average"
56
56
  puts "Optimized: #{optimized_avg.round(4)}ms average"
57
57
  puts "Speedup: #{speedup.round(1)}x faster"
58
-
58
+
59
59
  # Performance rating
60
60
  rating = case speedup
61
- when 0..2 then "🟡 Minor improvement"
62
- when 2..10 then "🟢 Good improvement"
63
- when 10..50 then "🟢 Great improvement"
64
- else "🚀 Exceptional improvement"
61
+ when 0..2 then '🟡 Minor improvement'
62
+ when 2..10 then '🟢 Good improvement'
63
+ when 10..50 then '🟢 Great improvement'
64
+ else '🚀 Exceptional improvement'
65
65
  end
66
-
66
+
67
67
  puts "Rating: #{rating}"
68
68
  puts
69
69
  end
70
70
 
71
71
  # Overall comparison
72
- puts "=" * 60
73
- puts "OVERALL PERFORMANCE ANALYSIS"
74
- puts "=" * 60
72
+ puts '=' * 60
73
+ puts 'OVERALL PERFORMANCE ANALYSIS'
74
+ puts '=' * 60
75
75
 
76
76
  # Test cache performance
77
77
  puts "\nCache Performance Test:"
78
- puts "-" * 30
78
+ puts '-' * 30
79
79
 
80
80
  # Clear caches
81
81
  StringToNumber.clear_caches!
@@ -107,17 +107,17 @@ class PerformanceComparison
107
107
 
108
108
  # Scalability test
109
109
  puts "\nScalability Comparison:"
110
- puts "-" * 30
110
+ puts '-' * 30
111
111
 
112
112
  scalability_tests = [
113
113
  'un', # 2 chars
114
114
  'vingt et un', # 11 chars
115
- 'mille deux cent trente-quatre', # 29 chars
115
+ 'mille deux cent trente-quatre', # 29 chars
116
116
  'soixante-quinze million trois cent quarante six mille sept cent quatre-vingt-dix neuf' # 85 chars
117
117
  ]
118
118
 
119
- puts "Input Length | Original | Optimized | Improvement"
120
- puts "-------------|----------|-----------|------------"
119
+ puts 'Input Length | Original | Optimized | Improvement'
120
+ puts '-------------|----------|-----------|------------'
121
121
 
122
122
  scalability_tests.each do |test|
123
123
  original_time = Benchmark.realtime do
@@ -132,24 +132,23 @@ class PerformanceComparison
132
132
  optimized_ms = (optimized_time / 1000) * 1000
133
133
  improvement = original_ms / optimized_ms
134
134
 
135
- puts "#{test.length.to_s.rjust(11)} | #{original_ms.round(4).to_s.rjust(8)} | #{optimized_ms.round(4).to_s.rjust(9)} | #{improvement.round(1).to_s.rjust(10)}x"
135
+ puts "#{test.length.to_s.rjust(11)} | #{original_ms.round(4).to_s.rjust(8)} | " \
136
+ "#{optimized_ms.round(4).to_s.rjust(9)} | #{improvement.round(1).to_s.rjust(10)}x"
136
137
  end
137
138
 
138
- puts "\n" + "=" * 60
139
- puts "SUMMARY"
140
- puts "=" * 60
141
- puts "✅ All test cases produce identical results"
142
- puts "🚀 Significant performance improvements across all test cases"
143
- puts "📈 Better scalability with input length"
144
- puts "💾 Effective caching reduces repeated conversion time"
145
- puts "🧠 Lower memory usage and object creation"
139
+ puts "\n#{'=' * 60}"
140
+ puts 'SUMMARY'
141
+ puts '=' * 60
142
+ puts '✅ All test cases produce identical results'
143
+ puts '🚀 Significant performance improvements across all test cases'
144
+ puts '📈 Better scalability with input length'
145
+ puts '💾 Effective caching reduces repeated conversion time'
146
+ puts '🧠 Lower memory usage and object creation'
146
147
  puts
147
- puts "The optimized implementation successfully addresses all identified"
148
- puts "performance bottlenecks while maintaining full compatibility."
148
+ puts 'The optimized implementation successfully addresses all identified'
149
+ puts 'performance bottlenecks while maintaining full compatibility.'
149
150
  end
150
151
  end
151
152
 
152
153
  # Run the comparison
153
- if __FILE__ == $0
154
- PerformanceComparison.run_comparison
155
- end
154
+ PerformanceComparison.run_comparison if __FILE__ == $PROGRAM_NAME
data/profile.rb CHANGED
@@ -8,93 +8,92 @@ require_relative 'lib/string_to_number'
8
8
 
9
9
  begin
10
10
  require 'ruby-prof'
11
-
11
+
12
12
  # Profile the most complex case
13
13
  test_input = 'soixante-quinze million trois cent quarante six mille sept cent quatre-vingt-dix neuf'
14
-
15
- puts "Profiling StringToNumber with input:"
14
+
15
+ puts 'Profiling StringToNumber with input:'
16
16
  puts "'#{test_input}'"
17
- puts "=" * 80
18
-
17
+ puts '=' * 80
18
+
19
19
  # Start profiling
20
20
  RubyProf.start
21
-
21
+
22
22
  # Run the conversion many times
23
23
  5000.times do
24
24
  StringToNumber.in_numbers(test_input)
25
25
  end
26
-
26
+
27
27
  # Stop profiling
28
28
  result = RubyProf.stop
29
-
29
+
30
30
  # Print results
31
31
  puts "\nTop 20 methods by total time:"
32
- puts "-" * 80
33
-
32
+ puts '-' * 80
33
+
34
34
  printer = RubyProf::FlatPrinter.new(result)
35
- printer.print(STDOUT, min_percent: 1)
36
-
35
+ printer.print($stdout, min_percent: 1)
36
+
37
37
  # Generate call graph
38
38
  puts "\n\nCall Graph Analysis:"
39
- puts "-" * 80
40
-
39
+ puts '-' * 80
40
+
41
41
  printer = RubyProf::CallTreePrinter.new(result)
42
42
  File.open('profile_output.txt', 'w') do |file|
43
43
  printer.print(file)
44
44
  end
45
- puts "Detailed call graph saved to: profile_output.txt"
46
-
45
+ puts 'Detailed call graph saved to: profile_output.txt'
46
+
47
47
  # Method-specific analysis
48
48
  puts "\n\nMethod Breakdown:"
49
- puts "-" * 80
50
-
49
+ puts '-' * 80
50
+
51
51
  result.threads.each do |thread|
52
52
  thread.methods.sort_by(&:total_time).reverse.first(10).each do |method|
53
53
  next if method.total_time < 0.01
54
-
55
- puts "#{method.full_name}"
54
+
55
+ puts method.full_name
56
56
  puts " Total time: #{(method.total_time * 1000).round(2)}ms"
57
57
  puts " Calls: #{method.called}"
58
58
  puts " Time per call: #{((method.total_time / method.called) * 1000).round(4)}ms"
59
59
  puts
60
60
  end
61
61
  end
62
-
63
62
  rescue LoadError
64
- puts "ruby-prof gem not available. Running basic timing analysis instead."
65
- puts "Install with: gem install ruby-prof"
63
+ puts 'ruby-prof gem not available. Running basic timing analysis instead.'
64
+ puts 'Install with: gem install ruby-prof'
66
65
  puts
67
-
66
+
68
67
  # Fallback: manual timing analysis
69
68
  require 'benchmark'
70
-
69
+
71
70
  test_cases = [
72
71
  'un',
73
- 'vingt et un',
72
+ 'vingt et un',
74
73
  'mille deux cent',
75
74
  'trois milliards cinq cents millions'
76
75
  ]
77
-
78
- puts "Manual Performance Analysis:"
79
- puts "=" * 40
80
-
76
+
77
+ puts 'Manual Performance Analysis:'
78
+ puts '=' * 40
79
+
81
80
  test_cases.each do |input|
82
81
  puts "\nAnalyzing: '#{input}'"
83
-
82
+
84
83
  # Time different aspects
85
84
  parser = nil
86
85
  init_time = Benchmark.realtime do
87
86
  1000.times { parser = StringToNumber::ToNumber.new(input) }
88
87
  end
89
-
88
+
90
89
  conversion_time = Benchmark.realtime do
91
90
  1000.times { parser.to_number }
92
91
  end
93
-
92
+
94
93
  total_time = Benchmark.realtime do
95
94
  1000.times { StringToNumber.in_numbers(input) }
96
95
  end
97
-
96
+
98
97
  puts " Initialization: #{(init_time * 1000).round(4)}ms per 1000 calls"
99
98
  puts " Conversion: #{(conversion_time * 1000).round(4)}ms per 1000 calls"
100
99
  puts " Total: #{(total_time * 1000).round(4)}ms per 1000 calls"
@@ -103,29 +102,29 @@ rescue LoadError
103
102
 
104
103
  # Test regex performance specifically
105
104
  puts "\n\nRegex Performance Test:"
106
- puts "=" * 40
107
-
108
- sample_input = "trois milliards cinq cents millions"
105
+ puts '=' * 40
106
+
107
+ sample_input = 'trois milliards cinq cents millions'
109
108
  parser = StringToNumber::ToNumber.new(sample_input)
110
109
  keys = parser.instance_variable_get(:@keys)
111
-
110
+
112
111
  puts "Keys pattern length: #{keys.length} characters"
113
-
112
+
114
113
  regex_time = Benchmark.realtime do
115
- 10000.times do
114
+ 10_000.times do
116
115
  /(?<f>.*?)\s?(?<m>#{keys})/.match(sample_input)
117
116
  end
118
117
  end
119
-
118
+
120
119
  puts "Regex matching time: #{(regex_time * 100).round(4)}ms per 10000 matches"
121
-
120
+
122
121
  # Test hash lookup performance
123
122
  lookup_time = Benchmark.realtime do
124
- 100000.times do
123
+ 100_000.times do
125
124
  StringToNumber::ToNumber::EXCEPTIONS['vingt']
126
125
  StringToNumber::ToNumber::POWERS_OF_TEN['millions']
127
126
  end
128
127
  end
129
-
128
+
130
129
  puts "Hash lookup time: #{(lookup_time * 10).round(4)}ms per 100000 lookups"
131
- end
130
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'string_to_number/version'
@@ -18,10 +20,11 @@ Gem::Specification.new do |spec|
18
20
  # to allow pushing to a single host or delete
19
21
  # this section to allow pushing to any host.
20
22
  if spec.respond_to?(:metadata)
21
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
23
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
24
+ spec.metadata['rubygems_mfa_required'] = 'true'
22
25
  else
23
26
  raise 'RubyGems 2.0 or newer is required to protect against ' \
24
- 'public gem pushes.'
27
+ 'public gem pushes.'
25
28
  end
26
29
 
27
30
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -30,8 +33,4 @@ Gem::Specification.new do |spec|
30
33
  spec.bindir = 'exe'
31
34
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
35
  spec.require_paths = ['lib']
33
-
34
- spec.add_development_dependency 'bundler'
35
- spec.add_development_dependency 'rake'
36
- spec.add_development_dependency 'rspec'
37
36
  end