activesupport 5.2.4.2 → 6.0.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +383 -397
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -2
  5. data/lib/active_support.rb +2 -1
  6. data/lib/active_support/actionable_error.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +28 -1
  8. data/lib/active_support/cache.rb +45 -23
  9. data/lib/active_support/cache/file_store.rb +22 -22
  10. data/lib/active_support/cache/mem_cache_store.rb +5 -0
  11. data/lib/active_support/cache/memory_store.rb +9 -2
  12. data/lib/active_support/cache/null_store.rb +5 -0
  13. data/lib/active_support/cache/redis_cache_store.rb +37 -10
  14. data/lib/active_support/callbacks.rb +16 -5
  15. data/lib/active_support/concern.rb +24 -1
  16. data/lib/active_support/configurable.rb +7 -11
  17. data/lib/active_support/core_ext/array.rb +1 -1
  18. data/lib/active_support/core_ext/array/access.rb +18 -6
  19. data/lib/active_support/core_ext/array/extract.rb +21 -0
  20. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
  21. data/lib/active_support/core_ext/class/attribute.rb +11 -16
  22. data/lib/active_support/core_ext/class/subclasses.rb +1 -1
  23. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  24. data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -47
  25. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  26. data/lib/active_support/core_ext/enumerable.rb +97 -73
  27. data/lib/active_support/core_ext/hash.rb +1 -2
  28. data/lib/active_support/core_ext/hash/compact.rb +2 -26
  29. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  30. data/lib/active_support/core_ext/hash/except.rb +1 -1
  31. data/lib/active_support/core_ext/hash/keys.rb +0 -29
  32. data/lib/active_support/core_ext/hash/slice.rb +3 -25
  33. data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
  34. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  35. data/lib/active_support/core_ext/kernel.rb +0 -1
  36. data/lib/active_support/core_ext/load_error.rb +1 -1
  37. data/lib/active_support/core_ext/module.rb +0 -1
  38. data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -10
  39. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +13 -19
  40. data/lib/active_support/core_ext/module/delegation.rb +33 -7
  41. data/lib/active_support/core_ext/module/introspection.rb +37 -13
  42. data/lib/active_support/core_ext/module/reachable.rb +1 -6
  43. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  44. data/lib/active_support/core_ext/numeric.rb +0 -1
  45. data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
  46. data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
  47. data/lib/active_support/core_ext/object/blank.rb +1 -2
  48. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  49. data/lib/active_support/core_ext/object/json.rb +1 -0
  50. data/lib/active_support/core_ext/object/try.rb +15 -7
  51. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  52. data/lib/active_support/core_ext/range/compare_range.rb +28 -13
  53. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  54. data/lib/active_support/core_ext/range/include_range.rb +6 -0
  55. data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
  56. data/lib/active_support/core_ext/regexp.rb +0 -4
  57. data/lib/active_support/core_ext/securerandom.rb +23 -3
  58. data/lib/active_support/core_ext/string/access.rb +8 -0
  59. data/lib/active_support/core_ext/string/filters.rb +42 -1
  60. data/lib/active_support/core_ext/string/inflections.rb +7 -2
  61. data/lib/active_support/core_ext/string/multibyte.rb +4 -3
  62. data/lib/active_support/core_ext/string/output_safety.rb +63 -5
  63. data/lib/active_support/core_ext/string/strip.rb +3 -1
  64. data/lib/active_support/core_ext/time/calculations.rb +31 -2
  65. data/lib/active_support/core_ext/uri.rb +1 -0
  66. data/lib/active_support/current_attributes.rb +8 -0
  67. data/lib/active_support/dependencies.rb +69 -16
  68. data/lib/active_support/dependencies/zeitwerk_integration.rb +118 -0
  69. data/lib/active_support/deprecation.rb +1 -1
  70. data/lib/active_support/deprecation/behaviors.rb +1 -1
  71. data/lib/active_support/deprecation/method_wrappers.rb +8 -20
  72. data/lib/active_support/deprecation/proxy_wrappers.rb +24 -5
  73. data/lib/active_support/descendants_tracker.rb +56 -9
  74. data/lib/active_support/duration.rb +6 -5
  75. data/lib/active_support/duration/iso8601_parser.rb +2 -3
  76. data/lib/active_support/duration/iso8601_serializer.rb +3 -4
  77. data/lib/active_support/encrypted_configuration.rb +0 -4
  78. data/lib/active_support/encrypted_file.rb +2 -1
  79. data/lib/active_support/evented_file_update_checker.rb +39 -9
  80. data/lib/active_support/execution_wrapper.rb +1 -0
  81. data/lib/active_support/gem_version.rb +4 -4
  82. data/lib/active_support/hash_with_indifferent_access.rb +22 -18
  83. data/lib/active_support/i18n.rb +1 -0
  84. data/lib/active_support/i18n_railtie.rb +13 -1
  85. data/lib/active_support/inflector/inflections.rb +1 -4
  86. data/lib/active_support/inflector/methods.rb +15 -27
  87. data/lib/active_support/inflector/transliterate.rb +47 -18
  88. data/lib/active_support/json/decoding.rb +23 -23
  89. data/lib/active_support/json/encoding.rb +6 -2
  90. data/lib/active_support/key_generator.rb +0 -32
  91. data/lib/active_support/lazy_load_hooks.rb +5 -1
  92. data/lib/active_support/locale/en.rb +31 -0
  93. data/lib/active_support/log_subscriber.rb +31 -8
  94. data/lib/active_support/logger.rb +0 -15
  95. data/lib/active_support/logger_silence.rb +28 -12
  96. data/lib/active_support/logger_thread_safe_level.rb +26 -4
  97. data/lib/active_support/message_encryptor.rb +3 -5
  98. data/lib/active_support/message_verifier.rb +3 -3
  99. data/lib/active_support/multibyte/chars.rb +29 -48
  100. data/lib/active_support/multibyte/unicode.rb +44 -281
  101. data/lib/active_support/notifications.rb +41 -4
  102. data/lib/active_support/notifications/fanout.rb +98 -13
  103. data/lib/active_support/notifications/instrumenter.rb +80 -8
  104. data/lib/active_support/number_helper.rb +7 -0
  105. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -2
  106. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
  107. data/lib/active_support/number_helper/number_to_human_converter.rb +3 -1
  108. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -1
  109. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  110. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -0
  111. data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -3
  112. data/lib/active_support/ordered_hash.rb +1 -1
  113. data/lib/active_support/ordered_options.rb +1 -1
  114. data/lib/active_support/parameter_filter.rb +129 -0
  115. data/lib/active_support/rails.rb +0 -6
  116. data/lib/active_support/reloader.rb +4 -5
  117. data/lib/active_support/security_utils.rb +1 -1
  118. data/lib/active_support/subscriber.rb +65 -26
  119. data/lib/active_support/tagged_logging.rb +13 -4
  120. data/lib/active_support/test_case.rb +91 -0
  121. data/lib/active_support/testing/assertions.rb +15 -1
  122. data/lib/active_support/testing/deprecation.rb +0 -1
  123. data/lib/active_support/testing/file_fixtures.rb +2 -0
  124. data/lib/active_support/testing/isolation.rb +2 -2
  125. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  126. data/lib/active_support/testing/parallelization.rb +128 -0
  127. data/lib/active_support/testing/stream.rb +1 -1
  128. data/lib/active_support/testing/time_helpers.rb +7 -7
  129. data/lib/active_support/time_with_zone.rb +15 -5
  130. data/lib/active_support/values/time_zone.rb +12 -7
  131. data/lib/active_support/xml_mini.rb +2 -9
  132. data/lib/active_support/xml_mini/jdom.rb +2 -2
  133. data/lib/active_support/xml_mini/libxml.rb +2 -2
  134. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  135. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  136. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  137. data/lib/active_support/xml_mini/rexml.rb +2 -2
  138. metadata +30 -8
  139. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  140. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "mutex_m"
4
4
  require "concurrent/map"
5
+ require "set"
5
6
 
6
7
  module ActiveSupport
7
8
  module Notifications
@@ -13,7 +14,8 @@ module ActiveSupport
13
14
  include Mutex_m
14
15
 
15
16
  def initialize
16
- @subscribers = []
17
+ @string_subscribers = Hash.new { |h, k| h[k] = [] }
18
+ @other_subscribers = []
17
19
  @listeners_for = Concurrent::Map.new
18
20
  super
19
21
  end
@@ -21,8 +23,13 @@ module ActiveSupport
21
23
  def subscribe(pattern = nil, callable = nil, &block)
22
24
  subscriber = Subscribers.new(pattern, callable || block)
23
25
  synchronize do
24
- @subscribers << subscriber
25
- @listeners_for.clear
26
+ if String === pattern
27
+ @string_subscribers[pattern] << subscriber
28
+ @listeners_for.delete(pattern)
29
+ else
30
+ @other_subscribers << subscriber
31
+ @listeners_for.clear
32
+ end
26
33
  end
27
34
  subscriber
28
35
  end
@@ -31,12 +38,19 @@ module ActiveSupport
31
38
  synchronize do
32
39
  case subscriber_or_name
33
40
  when String
34
- @subscribers.reject! { |s| s.matches?(subscriber_or_name) }
41
+ @string_subscribers[subscriber_or_name].clear
42
+ @listeners_for.delete(subscriber_or_name)
43
+ @other_subscribers.each { |sub| sub.unsubscribe!(subscriber_or_name) }
35
44
  else
36
- @subscribers.delete(subscriber_or_name)
45
+ pattern = subscriber_or_name.try(:pattern)
46
+ if String === pattern
47
+ @string_subscribers[pattern].delete(subscriber_or_name)
48
+ @listeners_for.delete(pattern)
49
+ else
50
+ @other_subscribers.delete(subscriber_or_name)
51
+ @listeners_for.clear
52
+ end
37
53
  end
38
-
39
- @listeners_for.clear
40
54
  end
41
55
  end
42
56
 
@@ -56,7 +70,8 @@ module ActiveSupport
56
70
  # this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
57
71
  @listeners_for[name] || synchronize do
58
72
  # use synchronisation when accessing @subscribers
59
- @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
73
+ @listeners_for[name] ||=
74
+ @string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
60
75
  end
61
76
  end
62
77
 
@@ -70,12 +85,29 @@ module ActiveSupport
70
85
 
71
86
  module Subscribers # :nodoc:
72
87
  def self.new(pattern, listener)
88
+ subscriber_class = Timed
89
+
73
90
  if listener.respond_to?(:start) && listener.respond_to?(:finish)
74
- subscriber = Evented.new pattern, listener
91
+ subscriber_class = Evented
75
92
  else
76
- subscriber = Timed.new pattern, listener
93
+ # Doing all this to detect a block like `proc { |x| }` vs
94
+ # `proc { |*x| }` or `proc { |**x| }`
95
+ if listener.respond_to?(:parameters)
96
+ params = listener.parameters
97
+ if params.length == 1 && params.first.first == :opt
98
+ subscriber_class = EventObject
99
+ end
100
+ end
77
101
  end
78
102
 
103
+ wrap_all pattern, subscriber_class.new(pattern, listener)
104
+ end
105
+
106
+ def self.event_object_subscriber(pattern, block)
107
+ wrap_all pattern, EventObject.new(pattern, block)
108
+ end
109
+
110
+ def self.wrap_all(pattern, subscriber)
79
111
  unless pattern
80
112
  AllMessages.new(subscriber)
81
113
  else
@@ -83,9 +115,33 @@ module ActiveSupport
83
115
  end
84
116
  end
85
117
 
118
+ class Matcher #:nodoc:
119
+ attr_reader :pattern, :exclusions
120
+
121
+ def self.wrap(pattern)
122
+ return pattern if String === pattern
123
+ new(pattern)
124
+ end
125
+
126
+ def initialize(pattern)
127
+ @pattern = pattern
128
+ @exclusions = Set.new
129
+ end
130
+
131
+ def unsubscribe!(name)
132
+ exclusions << -name if pattern === name
133
+ end
134
+
135
+ def ===(name)
136
+ pattern === name && !exclusions.include?(name)
137
+ end
138
+ end
139
+
86
140
  class Evented #:nodoc:
141
+ attr_reader :pattern
142
+
87
143
  def initialize(pattern, delegate)
88
- @pattern = pattern
144
+ @pattern = Matcher.wrap(pattern)
89
145
  @delegate = delegate
90
146
  @can_publish = delegate.respond_to?(:publish)
91
147
  end
@@ -105,11 +161,15 @@ module ActiveSupport
105
161
  end
106
162
 
107
163
  def subscribed_to?(name)
108
- @pattern === name
164
+ pattern === name
109
165
  end
110
166
 
111
167
  def matches?(name)
112
- @pattern && @pattern === name
168
+ pattern && pattern === name
169
+ end
170
+
171
+ def unsubscribe!(name)
172
+ pattern.unsubscribe!(name)
113
173
  end
114
174
  end
115
175
 
@@ -130,6 +190,27 @@ module ActiveSupport
130
190
  end
131
191
  end
132
192
 
193
+ class EventObject < Evented
194
+ def start(name, id, payload)
195
+ stack = Thread.current[:_event_stack] ||= []
196
+ event = build_event name, id, payload
197
+ event.start!
198
+ stack.push event
199
+ end
200
+
201
+ def finish(name, id, payload)
202
+ stack = Thread.current[:_event_stack]
203
+ event = stack.pop
204
+ event.finish!
205
+ @delegate.call event
206
+ end
207
+
208
+ private
209
+ def build_event(name, id, payload)
210
+ ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
211
+ end
212
+ end
213
+
133
214
  class AllMessages # :nodoc:
134
215
  def initialize(delegate)
135
216
  @delegate = delegate
@@ -151,6 +232,10 @@ module ActiveSupport
151
232
  true
152
233
  end
153
234
 
235
+ def unsubscribe!(*)
236
+ false
237
+ end
238
+
154
239
  alias :matches? :===
155
240
  end
156
241
  end
@@ -13,14 +13,15 @@ module ActiveSupport
13
13
  @notifier = notifier
14
14
  end
15
15
 
16
- # Instrument the given block by measuring the time taken to execute it
17
- # and publish it. Notice that events get sent even if an error occurs
18
- # in the passed-in block.
16
+ # Given a block, instrument it by measuring the time taken to execute
17
+ # and publish it. Without a block, simply send a message via the
18
+ # notifier. Notice that events get sent even if an error occurs in the
19
+ # passed-in block.
19
20
  def instrument(name, payload = {})
20
21
  # some of the listeners might have state
21
22
  listeners_state = start name, payload
22
23
  begin
23
- yield payload
24
+ yield payload if block_given?
24
25
  rescue Exception => e
25
26
  payload[:exception] = [e.class.name, e.message]
26
27
  payload[:exception_object] = e
@@ -52,8 +53,14 @@ module ActiveSupport
52
53
  end
53
54
 
54
55
  class Event
55
- attr_reader :name, :time, :transaction_id, :payload, :children
56
- attr_accessor :end
56
+ attr_reader :name, :time, :end, :transaction_id, :payload, :children
57
+
58
+ def self.clock_gettime_supported? # :nodoc:
59
+ defined?(Process::CLOCK_THREAD_CPUTIME_ID) &&
60
+ !Gem.win_platform? &&
61
+ !RUBY_PLATFORM.match?(/solaris/i)
62
+ end
63
+ private_class_method :clock_gettime_supported?
57
64
 
58
65
  def initialize(name, start, ending, transaction_id, payload)
59
66
  @name = name
@@ -62,7 +69,47 @@ module ActiveSupport
62
69
  @transaction_id = transaction_id
63
70
  @end = ending
64
71
  @children = []
65
- @duration = nil
72
+ @cpu_time_start = 0
73
+ @cpu_time_finish = 0
74
+ @allocation_count_start = 0
75
+ @allocation_count_finish = 0
76
+ end
77
+
78
+ # Record information at the time this event starts
79
+ def start!
80
+ @time = now
81
+ @cpu_time_start = now_cpu
82
+ @allocation_count_start = now_allocations
83
+ end
84
+
85
+ # Record information at the time this event finishes
86
+ def finish!
87
+ @cpu_time_finish = now_cpu
88
+ @end = now
89
+ @allocation_count_finish = now_allocations
90
+ end
91
+
92
+ def end=(ending)
93
+ ActiveSupport::Deprecation.deprecation_warning(:end=, :finish!)
94
+ @end = ending
95
+ end
96
+
97
+ # Returns the CPU time (in milliseconds) passed since the call to
98
+ # +start!+ and the call to +finish!+
99
+ def cpu_time
100
+ (@cpu_time_finish - @cpu_time_start) * 1000
101
+ end
102
+
103
+ # Returns the idle time time (in milliseconds) passed since the call to
104
+ # +start!+ and the call to +finish!+
105
+ def idle_time
106
+ duration - cpu_time
107
+ end
108
+
109
+ # Returns the number of allocations made since the call to +start!+ and
110
+ # the call to +finish!+
111
+ def allocations
112
+ @allocation_count_finish - @allocation_count_start
66
113
  end
67
114
 
68
115
  # Returns the difference in milliseconds between when the execution of the
@@ -78,7 +125,7 @@ module ActiveSupport
78
125
  #
79
126
  # @event.duration # => 1000.138
80
127
  def duration
81
- @duration ||= 1000.0 * (self.end - time)
128
+ 1000.0 * (self.end - time)
82
129
  end
83
130
 
84
131
  def <<(event)
@@ -88,6 +135,31 @@ module ActiveSupport
88
135
  def parent_of?(event)
89
136
  @children.include? event
90
137
  end
138
+
139
+ private
140
+ def now
141
+ Concurrent.monotonic_time
142
+ end
143
+
144
+ if clock_gettime_supported?
145
+ def now_cpu
146
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
147
+ end
148
+ else
149
+ def now_cpu
150
+ 0
151
+ end
152
+ end
153
+
154
+ if defined?(JRUBY_VERSION)
155
+ def now_allocations
156
+ 0
157
+ end
158
+ else
159
+ def now_allocations
160
+ GC.stat :total_allocated_objects
161
+ end
162
+ end
91
163
  end
92
164
  end
93
165
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/dependencies/autoload"
4
+
3
5
  module ActiveSupport
4
6
  module NumberHelper
5
7
  extend ActiveSupport::Autoload
@@ -85,6 +87,9 @@ module ActiveSupport
85
87
  # number given by <tt>:format</tt>). Accepts the same fields
86
88
  # than <tt>:format</tt>, except <tt>%n</tt> is here the
87
89
  # absolute value of the number.
90
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
91
+ # insignificant zeros after the decimal separator (defaults to
92
+ # +false+).
88
93
  #
89
94
  # ==== Examples
90
95
  #
@@ -100,6 +105,8 @@ module ActiveSupport
100
105
  # # => "&pound;1234567890,50"
101
106
  # number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
102
107
  # # => "1234567890,50 &pound;"
108
+ # number_to_currency(1234567890.50, strip_insignificant_zeros: true)
109
+ # # => "$1,234,567,890.5"
103
110
  def number_to_currency(number, options = {})
104
111
  NumberToCurrencyConverter.convert(number, options)
105
112
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/numeric/inquiry"
3
+ require "active_support/number_helper/number_converter"
4
4
 
5
5
  module ActiveSupport
6
6
  module NumberHelper
@@ -17,7 +17,7 @@ module ActiveSupport
17
17
  end
18
18
 
19
19
  rounded_number = NumberToRoundedConverter.convert(number, options)
20
- format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, options[:unit])
20
+ format.gsub("%n", rounded_number).gsub("%u", options[:unit])
21
21
  end
22
22
 
23
23
  private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/number_helper/number_converter"
4
+
3
5
  module ActiveSupport
4
6
  module NumberHelper
5
7
  class NumberToDelimitedConverter < NumberConverter #:nodoc:
@@ -14,7 +16,7 @@ module ActiveSupport
14
16
  private
15
17
 
16
18
  def parts
17
- left, right = number.to_s.split(".".freeze)
19
+ left, right = number.to_s.split(".")
18
20
  left.gsub!(delimiter_pattern) do |digit_to_delimit|
19
21
  "#{digit_to_delimit}#{options[:delimiter]}"
20
22
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/number_helper/number_converter"
4
+
3
5
  module ActiveSupport
4
6
  module NumberHelper
5
7
  class NumberToHumanConverter < NumberConverter # :nodoc:
@@ -25,7 +27,7 @@ module ActiveSupport
25
27
 
26
28
  rounded_number = NumberToRoundedConverter.convert(number, options)
27
29
  unit = determine_unit(units, exponent)
28
- format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, unit).strip
30
+ format.gsub("%n", rounded_number).gsub("%u", unit).strip
29
31
  end
30
32
 
31
33
  private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/number_helper/number_converter"
4
+
3
5
  module ActiveSupport
4
6
  module NumberHelper
5
7
  class NumberToHumanSizeConverter < NumberConverter #:nodoc:
@@ -22,7 +24,7 @@ module ActiveSupport
22
24
  human_size = number / (base**exponent)
23
25
  number_to_format = NumberToRoundedConverter.convert(human_size, options)
24
26
  end
25
- conversion_format.gsub("%n".freeze, number_to_format).gsub("%u".freeze, unit)
27
+ conversion_format.gsub("%n", number_to_format).gsub("%u", unit)
26
28
  end
27
29
 
28
30
  private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/number_helper/number_converter"
4
+
3
5
  module ActiveSupport
4
6
  module NumberHelper
5
7
  class NumberToPercentageConverter < NumberConverter # :nodoc:
@@ -7,7 +9,7 @@ module ActiveSupport
7
9
 
8
10
  def convert
9
11
  rounded_number = NumberToRoundedConverter.convert(number, options)
10
- options[:format].gsub("%n".freeze, rounded_number)
12
+ options[:format].gsub("%n", rounded_number)
11
13
  end
12
14
  end
13
15
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/number_helper/number_converter"
4
+
3
5
  module ActiveSupport
4
6
  module NumberHelper
5
7
  class NumberToPhoneConverter < NumberConverter #:nodoc:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/number_helper/number_converter"
4
+
3
5
  module ActiveSupport
4
6
  module NumberHelper
5
7
  class NumberToRoundedConverter < NumberConverter # :nodoc:
@@ -20,9 +22,9 @@ module ActiveSupport
20
22
  formatted_string =
21
23
  if BigDecimal === rounded_number && rounded_number.finite?
22
24
  s = rounded_number.to_s("F")
23
- s << "0".freeze * precision
24
- a, b = s.split(".".freeze, 2)
25
- a << ".".freeze
25
+ s << "0" * precision
26
+ a, b = s.split(".", 2)
27
+ a << "."
26
28
  a << b[0, precision]
27
29
  else
28
30
  "%00.#{precision}f" % rounded_number