activesupport 6.0.0 → 6.1.3

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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +381 -349
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/active_support.rb +13 -1
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +3 -4
  8. data/lib/active_support/benchmarkable.rb +1 -1
  9. data/lib/active_support/cache.rb +101 -59
  10. data/lib/active_support/cache/file_store.rb +11 -11
  11. data/lib/active_support/cache/mem_cache_store.rb +34 -33
  12. data/lib/active_support/cache/memory_store.rb +52 -31
  13. data/lib/active_support/cache/null_store.rb +3 -3
  14. data/lib/active_support/cache/redis_cache_store.rb +38 -33
  15. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  16. data/lib/active_support/callbacks.rb +65 -59
  17. data/lib/active_support/concern.rb +46 -2
  18. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  19. data/lib/active_support/concurrency/share_lock.rb +0 -1
  20. data/lib/active_support/configurable.rb +3 -3
  21. data/lib/active_support/configuration_file.rb +46 -0
  22. data/lib/active_support/core_ext.rb +1 -1
  23. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  24. data/lib/active_support/core_ext/benchmark.rb +2 -2
  25. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  26. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  27. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  28. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  29. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  30. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  31. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  32. data/lib/active_support/core_ext/enumerable.rb +76 -4
  33. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  34. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  35. data/lib/active_support/core_ext/hash/except.rb +1 -1
  36. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  37. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  38. data/lib/active_support/core_ext/load_error.rb +1 -1
  39. data/lib/active_support/core_ext/marshal.rb +2 -0
  40. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  41. data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
  42. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
  43. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  44. data/lib/active_support/core_ext/module/delegation.rb +46 -29
  45. data/lib/active_support/core_ext/module/introspection.rb +2 -25
  46. data/lib/active_support/core_ext/name_error.rb +29 -2
  47. data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
  48. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  49. data/lib/active_support/core_ext/object/json.rb +13 -2
  50. data/lib/active_support/core_ext/object/try.rb +4 -2
  51. data/lib/active_support/core_ext/range/compare_range.rb +15 -3
  52. data/lib/active_support/core_ext/range/each.rb +0 -1
  53. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  54. data/lib/active_support/core_ext/regexp.rb +8 -1
  55. data/lib/active_support/core_ext/string/access.rb +5 -24
  56. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  57. data/lib/active_support/core_ext/string/inflections.rb +38 -4
  58. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  59. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  60. data/lib/active_support/core_ext/string/output_safety.rb +12 -11
  61. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  62. data/lib/active_support/core_ext/symbol.rb +3 -0
  63. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  64. data/lib/active_support/core_ext/time/calculations.rb +27 -3
  65. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  66. data/lib/active_support/core_ext/uri.rb +5 -1
  67. data/lib/active_support/current_attributes.rb +7 -2
  68. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  69. data/lib/active_support/dependencies.rb +42 -20
  70. data/lib/active_support/dependencies/zeitwerk_integration.rb +9 -2
  71. data/lib/active_support/deprecation.rb +6 -1
  72. data/lib/active_support/deprecation/behaviors.rb +15 -2
  73. data/lib/active_support/deprecation/disallowed.rb +56 -0
  74. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  75. data/lib/active_support/deprecation/method_wrappers.rb +13 -6
  76. data/lib/active_support/deprecation/proxy_wrappers.rb +6 -2
  77. data/lib/active_support/deprecation/reporting.rb +50 -7
  78. data/lib/active_support/descendants_tracker.rb +6 -3
  79. data/lib/active_support/duration.rb +86 -35
  80. data/lib/active_support/duration/iso8601_parser.rb +0 -1
  81. data/lib/active_support/duration/iso8601_serializer.rb +15 -10
  82. data/lib/active_support/encrypted_file.rb +20 -3
  83. data/lib/active_support/environment_inquirer.rb +20 -0
  84. data/lib/active_support/evented_file_update_checker.rb +69 -134
  85. data/lib/active_support/file_update_checker.rb +0 -1
  86. data/lib/active_support/fork_tracker.rb +62 -0
  87. data/lib/active_support/gem_version.rb +2 -2
  88. data/lib/active_support/hash_with_indifferent_access.rb +43 -24
  89. data/lib/active_support/i18n_railtie.rb +15 -16
  90. data/lib/active_support/inflector/inflections.rb +1 -3
  91. data/lib/active_support/inflector/methods.rb +36 -33
  92. data/lib/active_support/inflector/transliterate.rb +4 -4
  93. data/lib/active_support/json/decoding.rb +4 -5
  94. data/lib/active_support/json/encoding.rb +5 -1
  95. data/lib/active_support/key_generator.rb +1 -1
  96. data/lib/active_support/lazy_load_hooks.rb +0 -1
  97. data/lib/active_support/locale/en.rb +4 -2
  98. data/lib/active_support/locale/en.yml +7 -3
  99. data/lib/active_support/log_subscriber.rb +8 -1
  100. data/lib/active_support/logger.rb +2 -2
  101. data/lib/active_support/logger_silence.rb +2 -26
  102. data/lib/active_support/logger_thread_safe_level.rb +34 -12
  103. data/lib/active_support/message_encryptor.rb +5 -8
  104. data/lib/active_support/message_verifier.rb +7 -7
  105. data/lib/active_support/messages/metadata.rb +11 -2
  106. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  107. data/lib/active_support/messages/rotator.rb +10 -9
  108. data/lib/active_support/multibyte/chars.rb +5 -44
  109. data/lib/active_support/multibyte/unicode.rb +9 -84
  110. data/lib/active_support/notifications.rb +32 -5
  111. data/lib/active_support/notifications/fanout.rb +23 -8
  112. data/lib/active_support/notifications/instrumenter.rb +7 -16
  113. data/lib/active_support/number_helper.rb +33 -14
  114. data/lib/active_support/number_helper/number_converter.rb +5 -6
  115. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -7
  116. data/lib/active_support/number_helper/number_to_delimited_converter.rb +0 -1
  117. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -2
  118. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -2
  119. data/lib/active_support/number_helper/number_to_phone_converter.rb +0 -1
  120. data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -4
  121. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  122. data/lib/active_support/option_merger.rb +22 -3
  123. data/lib/active_support/ordered_hash.rb +1 -1
  124. data/lib/active_support/ordered_options.rb +13 -3
  125. data/lib/active_support/parameter_filter.rb +17 -13
  126. data/lib/active_support/per_thread_registry.rb +1 -1
  127. data/lib/active_support/rails.rb +1 -4
  128. data/lib/active_support/railtie.rb +23 -1
  129. data/lib/active_support/rescuable.rb +4 -4
  130. data/lib/active_support/secure_compare_rotator.rb +51 -0
  131. data/lib/active_support/security_utils.rb +19 -12
  132. data/lib/active_support/string_inquirer.rb +4 -3
  133. data/lib/active_support/subscriber.rb +12 -7
  134. data/lib/active_support/tagged_logging.rb +29 -4
  135. data/lib/active_support/testing/assertions.rb +18 -11
  136. data/lib/active_support/testing/parallelization.rb +12 -89
  137. data/lib/active_support/testing/parallelization/server.rb +78 -0
  138. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  139. data/lib/active_support/testing/stream.rb +0 -1
  140. data/lib/active_support/testing/time_helpers.rb +40 -5
  141. data/lib/active_support/time_with_zone.rb +67 -43
  142. data/lib/active_support/values/time_zone.rb +20 -10
  143. data/lib/active_support/xml_mini.rb +0 -1
  144. data/lib/active_support/xml_mini/jdom.rb +0 -1
  145. data/lib/active_support/xml_mini/rexml.rb +8 -1
  146. metadata +39 -38
  147. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  148. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  149. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  150. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  151. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  152. data/lib/active_support/core_ext/range/include_range.rb +0 -9
@@ -5,53 +5,19 @@ module ActiveSupport
5
5
  module Unicode
6
6
  extend self
7
7
 
8
- # A list of all available normalization forms.
9
- # See https://www.unicode.org/reports/tr15/tr15-29.html for more
10
- # information about normalization.
11
- NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
12
-
13
- NORMALIZATION_FORM_ALIASES = { # :nodoc:
14
- c: :nfc,
15
- d: :nfd,
16
- kc: :nfkc,
17
- kd: :nfkd
18
- }
19
-
20
8
  # The Unicode version that is supported by the implementation
21
9
  UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
22
10
 
23
- # The default normalization used for operations that require
24
- # normalization. It can be set to any of the normalizations
25
- # in NORMALIZATION_FORMS.
26
- #
27
- # ActiveSupport::Multibyte::Unicode.default_normalization_form = :c
28
- attr_accessor :default_normalization_form
29
- @default_normalization_form = :kc
30
-
31
- # Unpack the string at grapheme boundaries. Returns a list of character
32
- # lists.
33
- #
34
- # Unicode.unpack_graphemes('क्षि') # => [[2325, 2381], [2359], [2367]]
35
- # Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]]
36
- def unpack_graphemes(string)
37
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
38
- ActiveSupport::Multibyte::Unicode#unpack_graphemes is deprecated and will be
39
- removed from Rails 6.1. Use string.scan(/\X/).map(&:codepoints) instead.
40
- MSG
41
-
42
- string.scan(/\X/).map(&:codepoints)
11
+ def default_normalization_form
12
+ ActiveSupport::Deprecation.warn(
13
+ "ActiveSupport::Multibyte::Unicode.default_normalization_form is deprecated and will be removed in Rails 6.2."
14
+ )
43
15
  end
44
16
 
45
- # Reverse operation of unpack_graphemes.
46
- #
47
- # Unicode.pack_graphemes(Unicode.unpack_graphemes('क्षि')) # => 'क्षि'
48
- def pack_graphemes(unpacked)
49
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
50
- ActiveSupport::Multibyte::Unicode#pack_graphemes is deprecated and will be
51
- removed from Rails 6.1. Use array.flatten.pack("U*") instead.
52
- MSG
53
-
54
- unpacked.flatten.pack("U*")
17
+ def default_normalization_form=(_)
18
+ ActiveSupport::Deprecation.warn(
19
+ "ActiveSupport::Multibyte::Unicode.default_normalization_form= is deprecated and will be removed in Rails 6.2."
20
+ )
55
21
  end
56
22
 
57
23
  # Decompose composed characters to the decomposed form.
@@ -76,7 +42,7 @@ module ActiveSupport
76
42
  # Passing +true+ will forcibly tidy all bytes, assuming that the string's
77
43
  # encoding is entirely CP1252 or ISO-8859-1.
78
44
  def tidy_bytes(string, force = false)
79
- return string if string.empty?
45
+ return string if string.empty? || string.ascii_only?
80
46
  return recode_windows1252_chars(string) if force
81
47
  string.scrub { |bad| recode_windows1252_chars(bad) }
82
48
  end
@@ -107,48 +73,7 @@ module ActiveSupport
107
73
  end
108
74
  end
109
75
 
110
- # Returns the KC normalization of the string by default. NFKC is
111
- # considered the best normalization form for passing strings to databases
112
- # and validations.
113
- #
114
- # * <tt>string</tt> - The string to perform normalization on.
115
- # * <tt>form</tt> - The form you want to normalize in. Should be one of
116
- # the following: <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>.
117
- # Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
118
- def normalize(string, form = nil)
119
- form ||= @default_normalization_form
120
-
121
- # See https://www.unicode.org/reports/tr15, Table 1
122
- if alias_form = NORMALIZATION_FORM_ALIASES[form]
123
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
124
- ActiveSupport::Multibyte::Unicode#normalize is deprecated and will be
125
- removed from Rails 6.1. Use String#unicode_normalize(:#{alias_form}) instead.
126
- MSG
127
-
128
- string.unicode_normalize(alias_form)
129
- else
130
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
131
- ActiveSupport::Multibyte::Unicode#normalize is deprecated and will be
132
- removed from Rails 6.1. Use String#unicode_normalize instead.
133
- MSG
134
-
135
- raise ArgumentError, "#{form} is not a valid normalization variant", caller
136
- end
137
- end
138
-
139
- %w(downcase upcase swapcase).each do |method|
140
- define_method(method) do |string|
141
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
142
- ActiveSupport::Multibyte::Unicode##{method} is deprecated and
143
- will be removed from Rails 6.1. Use String methods directly.
144
- MSG
145
-
146
- string.send(method)
147
- end
148
- end
149
-
150
76
  private
151
-
152
77
  def recode_windows1252_chars(string)
153
78
  string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
154
79
  end
@@ -38,6 +38,19 @@ module ActiveSupport
38
38
  # payload # => Hash, the payload
39
39
  # end
40
40
  #
41
+ # Here, the +start+ and +finish+ values represent wall-clock time. If you are
42
+ # concerned about accuracy, you can register a monotonic subscriber.
43
+ #
44
+ # ActiveSupport::Notifications.monotonic_subscribe('render') do |name, start, finish, id, payload|
45
+ # name # => String, name of the event (such as 'render' from above)
46
+ # start # => Monotonic time, when the instrumented block started execution
47
+ # finish # => Monotonic time, when the instrumented block ended execution
48
+ # id # => String, unique ID for the instrumenter that fired the event
49
+ # payload # => Hash, the payload
50
+ # end
51
+ #
52
+ # The +start+ and +finish+ values above represent monotonic time.
53
+ #
41
54
  # For instance, let's store all "render" events in an array:
42
55
  #
43
56
  # events = []
@@ -135,6 +148,16 @@ module ActiveSupport
135
148
  # during the execution of the block. The callback is unsubscribed automatically
136
149
  # after that.
137
150
  #
151
+ # To record +started+ and +finished+ values with monotonic time,
152
+ # specify the optional <tt>:monotonic</tt> option to the
153
+ # <tt>subscribed</tt> method. The <tt>:monotonic</tt> option is set
154
+ # to +false+ by default.
155
+ #
156
+ # callback = lambda {|name, started, finished, unique_id, payload| ... }
157
+ # ActiveSupport::Notifications.subscribed(callback, "sql.active_record", monotonic: true) do
158
+ # ...
159
+ # end
160
+ #
138
161
  # === Manual Unsubscription
139
162
  #
140
163
  # The +subscribe+ method returns a subscriber object:
@@ -155,7 +178,7 @@ module ActiveSupport
155
178
  #
156
179
  # Subscribers using a regexp or other pattern-matching object will remain subscribed
157
180
  # to all events that match their original pattern, unless those events match a string
158
- # passed to `unsubscribe`:
181
+ # passed to +unsubscribe+:
159
182
  #
160
183
  # subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
161
184
  # ActiveSupport::Notifications.unsubscribe('render_template.action_view')
@@ -208,12 +231,16 @@ module ActiveSupport
208
231
  # ActiveSupport::Notifications.subscribe(/render/) do |event|
209
232
  # @event = event
210
233
  # end
211
- def subscribe(*args, &block)
212
- notifier.subscribe(*args, &block)
234
+ def subscribe(pattern = nil, callback = nil, &block)
235
+ notifier.subscribe(pattern, callback, monotonic: false, &block)
236
+ end
237
+
238
+ def monotonic_subscribe(pattern = nil, callback = nil, &block)
239
+ notifier.subscribe(pattern, callback, monotonic: true, &block)
213
240
  end
214
241
 
215
- def subscribed(callback, *args, &block)
216
- subscriber = subscribe(*args, &callback)
242
+ def subscribed(callback, pattern = nil, monotonic: false, &block)
243
+ subscriber = notifier.subscribe(pattern, callback, monotonic: monotonic)
217
244
  yield
218
245
  ensure
219
246
  unsubscribe(subscriber)
@@ -3,6 +3,7 @@
3
3
  require "mutex_m"
4
4
  require "concurrent/map"
5
5
  require "set"
6
+ require "active_support/core_ext/object/try"
6
7
 
7
8
  module ActiveSupport
8
9
  module Notifications
@@ -20,8 +21,8 @@ module ActiveSupport
20
21
  super
21
22
  end
22
23
 
23
- def subscribe(pattern = nil, callable = nil, &block)
24
- subscriber = Subscribers.new(pattern, callable || block)
24
+ def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
25
+ subscriber = Subscribers.new(pattern, callable || block, monotonic)
25
26
  synchronize do
26
27
  if String === pattern
27
28
  @string_subscribers[pattern] << subscriber
@@ -84,8 +85,8 @@ module ActiveSupport
84
85
  end
85
86
 
86
87
  module Subscribers # :nodoc:
87
- def self.new(pattern, listener)
88
- subscriber_class = Timed
88
+ def self.new(pattern, listener, monotonic)
89
+ subscriber_class = monotonic ? MonotonicTimed : Timed
89
90
 
90
91
  if listener.respond_to?(:start) && listener.respond_to?(:finish)
91
92
  subscriber_class = Evented
@@ -103,10 +104,6 @@ module ActiveSupport
103
104
  wrap_all pattern, subscriber_class.new(pattern, listener)
104
105
  end
105
106
 
106
- def self.event_object_subscriber(pattern, block)
107
- wrap_all pattern, EventObject.new(pattern, block)
108
- end
109
-
110
107
  def self.wrap_all(pattern, subscriber)
111
108
  unless pattern
112
109
  AllMessages.new(subscriber)
@@ -190,6 +187,23 @@ module ActiveSupport
190
187
  end
191
188
  end
192
189
 
190
+ class MonotonicTimed < Evented # :nodoc:
191
+ def publish(name, *args)
192
+ @delegate.call name, *args
193
+ end
194
+
195
+ def start(name, id, payload)
196
+ timestack = Thread.current[:_timestack_monotonic] ||= []
197
+ timestack.push Concurrent.monotonic_time
198
+ end
199
+
200
+ def finish(name, id, payload)
201
+ timestack = Thread.current[:_timestack_monotonic]
202
+ started = timestack.pop
203
+ @delegate.call(name, started, Concurrent.monotonic_time, id, payload)
204
+ end
205
+ end
206
+
193
207
  class EventObject < Evented
194
208
  def start(name, id, payload)
195
209
  stack = Thread.current[:_event_stack] ||= []
@@ -201,6 +215,7 @@ module ActiveSupport
201
215
  def finish(name, id, payload)
202
216
  stack = Thread.current[:_event_stack]
203
217
  event = stack.pop
218
+ event.payload = payload
204
219
  event.finish!
205
220
  @delegate.call event
206
221
  end
@@ -46,20 +46,14 @@ module ActiveSupport
46
46
  end
47
47
 
48
48
  private
49
-
50
49
  def unique_id
51
50
  SecureRandom.hex(10)
52
51
  end
53
52
  end
54
53
 
55
54
  class Event
56
- attr_reader :name, :time, :end, :transaction_id, :payload, :children
57
-
58
- def self.clock_gettime_supported? # :nodoc:
59
- defined?(Process::CLOCK_PROCESS_CPUTIME_ID) &&
60
- !Gem.win_platform?
61
- end
62
- private_class_method :clock_gettime_supported?
55
+ attr_reader :name, :time, :end, :transaction_id, :children
56
+ attr_accessor :payload
63
57
 
64
58
  def initialize(name, start, ending, transaction_id, payload)
65
59
  @name = name
@@ -88,11 +82,6 @@ module ActiveSupport
88
82
  @allocation_count_finish = now_allocations
89
83
  end
90
84
 
91
- def end=(ending)
92
- ActiveSupport::Deprecation.deprecation_warning(:end=, :finish!)
93
- @end = ending
94
- end
95
-
96
85
  # Returns the CPU time (in milliseconds) passed since the call to
97
86
  # +start!+ and the call to +finish!+
98
87
  def cpu_time
@@ -140,11 +129,13 @@ module ActiveSupport
140
129
  Concurrent.monotonic_time
141
130
  end
142
131
 
143
- if clock_gettime_supported?
132
+ begin
133
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
134
+
144
135
  def now_cpu
145
- Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID)
136
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
146
137
  end
147
- else
138
+ rescue
148
139
  def now_cpu
149
140
  0
150
141
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/dependencies/autoload"
4
-
5
3
  module ActiveSupport
6
4
  module NumberHelper
7
5
  extend ActiveSupport::Autoload
@@ -73,6 +71,8 @@ module ActiveSupport
73
71
  # (defaults to current locale).
74
72
  # * <tt>:precision</tt> - Sets the level of precision (defaults
75
73
  # to 2).
74
+ # * <tt>:round_mode</tt> - Determine how rounding is performed
75
+ # (defaults to :default. See BigDecimal::mode)
76
76
  # * <tt>:unit</tt> - Sets the denomination of the currency
77
77
  # (defaults to "$").
78
78
  # * <tt>:separator</tt> - Sets the separator between the units
@@ -99,6 +99,10 @@ module ActiveSupport
99
99
  # number_to_currency(1234567890.506, locale: :fr) # => "1 234 567 890,51 €"
100
100
  # number_to_currency('123a456') # => "$123a456"
101
101
  #
102
+ # number_to_currency("123a456", raise: true) # => InvalidNumberError
103
+ #
104
+ # number_to_currency(-0.456789, precision: 0)
105
+ # # => "$0"
102
106
  # number_to_currency(-1234567890.50, negative_format: '(%u%n)')
103
107
  # # => "($1,234,567,890.50)"
104
108
  # number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '')
@@ -107,6 +111,8 @@ module ActiveSupport
107
111
  # # => "1234567890,50 &pound;"
108
112
  # number_to_currency(1234567890.50, strip_insignificant_zeros: true)
109
113
  # # => "$1,234,567,890.5"
114
+ # number_to_currency(1234567890.50, precision: 0, round_mode: :up)
115
+ # # => "$1,234,567,891"
110
116
  def number_to_currency(number, options = {})
111
117
  NumberToCurrencyConverter.convert(number, options)
112
118
  end
@@ -120,6 +126,8 @@ module ActiveSupport
120
126
  # (defaults to current locale).
121
127
  # * <tt>:precision</tt> - Sets the precision of the number
122
128
  # (defaults to 3). Keeps the number's precision if +nil+.
129
+ # * <tt>:round_mode</tt> - Determine how rounding is performed
130
+ # (defaults to :default. See BigDecimal::mode)
123
131
  # * <tt>:significant</tt> - If +true+, precision will be the number
124
132
  # of significant_digits. If +false+, the number of fractional
125
133
  # digits (defaults to +false+).
@@ -135,15 +143,16 @@ module ActiveSupport
135
143
  #
136
144
  # ==== Examples
137
145
  #
138
- # number_to_percentage(100) # => "100.000%"
139
- # number_to_percentage('98') # => "98.000%"
140
- # number_to_percentage(100, precision: 0) # => "100%"
141
- # number_to_percentage(1000, delimiter: '.', separator: ',') # => "1.000,000%"
142
- # number_to_percentage(302.24398923423, precision: 5) # => "302.24399%"
143
- # number_to_percentage(1000, locale: :fr) # => "1000,000%"
144
- # number_to_percentage(1000, precision: nil) # => "1000%"
145
- # number_to_percentage('98a') # => "98a%"
146
- # number_to_percentage(100, format: '%n %') # => "100.000 %"
146
+ # number_to_percentage(100) # => "100.000%"
147
+ # number_to_percentage('98') # => "98.000%"
148
+ # number_to_percentage(100, precision: 0) # => "100%"
149
+ # number_to_percentage(1000, delimiter: '.', separator: ',') # => "1.000,000%"
150
+ # number_to_percentage(302.24398923423, precision: 5) # => "302.24399%"
151
+ # number_to_percentage(1000, locale: :fr) # => "1000,000%"
152
+ # number_to_percentage(1000, precision: nil) # => "1000%"
153
+ # number_to_percentage('98a') # => "98a%"
154
+ # number_to_percentage(100, format: '%n %') # => "100.000 %"
155
+ # number_to_percentage(302.24398923423, precision: 5, round_mode: :down) # => "302.24398%"
147
156
  def number_to_percentage(number, options = {})
148
157
  NumberToPercentageConverter.convert(number, options)
149
158
  end
@@ -194,6 +203,8 @@ module ActiveSupport
194
203
  # (defaults to current locale).
195
204
  # * <tt>:precision</tt> - Sets the precision of the number
196
205
  # (defaults to 3). Keeps the number's precision if +nil+.
206
+ # * <tt>:round_mode</tt> - Determine how rounding is performed
207
+ # (defaults to :default. See BigDecimal::mode)
197
208
  # * <tt>:significant</tt> - If +true+, precision will be the number
198
209
  # of significant_digits. If +false+, the number of fractional
199
210
  # digits (defaults to +false+).
@@ -215,6 +226,7 @@ module ActiveSupport
215
226
  # number_to_rounded(111.2345, precision: 1, significant: true) # => "100"
216
227
  # number_to_rounded(13, precision: 5, significant: true) # => "13.000"
217
228
  # number_to_rounded(13, precision: nil) # => "13"
229
+ # number_to_rounded(389.32314, precision: 0, round_mode: :up) # => "390"
218
230
  # number_to_rounded(111.234, locale: :fr) # => "111,234"
219
231
  #
220
232
  # number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
@@ -228,7 +240,7 @@ module ActiveSupport
228
240
  end
229
241
 
230
242
  # Formats the bytes in +number+ into a more understandable
231
- # representation (e.g., giving it 1500 yields 1.5 KB). This
243
+ # representation (e.g., giving it 1500 yields 1.46 KB). This
232
244
  # method is useful for reporting file sizes to users. You can
233
245
  # customize the format in the +options+ hash.
234
246
  #
@@ -241,6 +253,8 @@ module ActiveSupport
241
253
  # (defaults to current locale).
242
254
  # * <tt>:precision</tt> - Sets the precision of the number
243
255
  # (defaults to 3).
256
+ # * <tt>:round_mode</tt> - Determine how rounding is performed
257
+ # (defaults to :default. See BigDecimal::mode)
244
258
  # * <tt>:significant</tt> - If +true+, precision will be the number
245
259
  # of significant_digits. If +false+, the number of fractional
246
260
  # digits (defaults to +true+)
@@ -264,6 +278,7 @@ module ActiveSupport
264
278
  # number_to_human_size(1234567890123456789) # => "1.07 EB"
265
279
  # number_to_human_size(1234567, precision: 2) # => "1.2 MB"
266
280
  # number_to_human_size(483989, precision: 2) # => "470 KB"
281
+ # number_to_human_size(483989, precision: 2, round_mode: :up) # => "480 KB"
267
282
  # number_to_human_size(1234567, precision: 2, separator: ',') # => "1,2 MB"
268
283
  # number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB"
269
284
  # number_to_human_size(524288000, precision: 5) # => "500 MB"
@@ -272,7 +287,7 @@ module ActiveSupport
272
287
  end
273
288
 
274
289
  # Pretty prints (formats and approximates) a number in a way it
275
- # is more readable by humans (eg.: 1200000000 becomes "1.2
290
+ # is more readable by humans (e.g.: 1200000000 becomes "1.2
276
291
  # Billion"). This is useful for numbers that can get very large
277
292
  # (and too hard to read).
278
293
  #
@@ -280,7 +295,7 @@ module ActiveSupport
280
295
  # size.
281
296
  #
282
297
  # You can also define your own unit-quantifier names if you want
283
- # to use other decimal units (eg.: 1500 becomes "1.5
298
+ # to use other decimal units (e.g.: 1500 becomes "1.5
284
299
  # kilometers", 0.150 becomes "150 milliliters", etc). You may
285
300
  # define a wide range of unit quantifiers, even fractional ones
286
301
  # (centi, deci, mili, etc).
@@ -291,6 +306,8 @@ module ActiveSupport
291
306
  # (defaults to current locale).
292
307
  # * <tt>:precision</tt> - Sets the precision of the number
293
308
  # (defaults to 3).
309
+ # * <tt>:round_mode</tt> - Determine how rounding is performed
310
+ # (defaults to :default. See BigDecimal::mode)
294
311
  # * <tt>:significant</tt> - If +true+, precision will be the number
295
312
  # of significant_digits. If +false+, the number of fractional
296
313
  # digits (defaults to +true+)
@@ -328,6 +345,8 @@ module ActiveSupport
328
345
  # number_to_human(1234567890123456789) # => "1230 Quadrillion"
329
346
  # number_to_human(489939, precision: 2) # => "490 Thousand"
330
347
  # number_to_human(489939, precision: 4) # => "489.9 Thousand"
348
+ # number_to_human(489939, precision: 2
349
+ # , round_mode: :down) # => "480 Thousand"
331
350
  # number_to_human(1234567, precision: 4,
332
351
  # significant: false) # => "1.2346 Million"
333
352
  # number_to_human(1234567, precision: 1,