activesupport 4.2.0 → 5.2.0

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 (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +54 -21
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration.rb +326 -30
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module NumberHelper
3
5
  extend ActiveSupport::Autoload
4
6
 
5
7
  eager_autoload do
6
8
  autoload :NumberConverter
9
+ autoload :RoundingHelper
7
10
  autoload :NumberToRoundedConverter
8
11
  autoload :NumberToDelimitedConverter
9
12
  autoload :NumberToHumanConverter
@@ -15,7 +18,7 @@ module ActiveSupport
15
18
 
16
19
  extend self
17
20
 
18
- # Formats a +number+ into a US phone number (e.g., (555)
21
+ # Formats a +number+ into a phone number (US by default e.g., (555)
19
22
  # 123-9876). You can customize the format in the +options+ hash.
20
23
  #
21
24
  # ==== Options
@@ -27,19 +30,26 @@ module ActiveSupport
27
30
  # end of the generated number.
28
31
  # * <tt>:country_code</tt> - Sets the country code for the phone
29
32
  # number.
33
+ # * <tt>:pattern</tt> - Specifies how the number is divided into three
34
+ # groups with the custom regexp to override the default format.
30
35
  # ==== Examples
31
36
  #
32
- # number_to_phone(5551234) # => 555-1234
33
- # number_to_phone('5551234') # => 555-1234
34
- # number_to_phone(1235551234) # => 123-555-1234
35
- # number_to_phone(1235551234, area_code: true) # => (123) 555-1234
36
- # number_to_phone(1235551234, delimiter: ' ') # => 123 555 1234
37
- # number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555
38
- # number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234
39
- # number_to_phone('123a456') # => 123a456
37
+ # number_to_phone(5551234) # => "555-1234"
38
+ # number_to_phone('5551234') # => "555-1234"
39
+ # number_to_phone(1235551234) # => "123-555-1234"
40
+ # number_to_phone(1235551234, area_code: true) # => "(123) 555-1234"
41
+ # number_to_phone(1235551234, delimiter: ' ') # => "123 555 1234"
42
+ # number_to_phone(1235551234, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
43
+ # number_to_phone(1235551234, country_code: 1) # => "+1-123-555-1234"
44
+ # number_to_phone('123a456') # => "123a456"
40
45
  #
41
46
  # number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: '.')
42
- # # => +1.123.555.1234 x 1343
47
+ # # => "+1.123.555.1234 x 1343"
48
+ #
49
+ # number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true)
50
+ # # => "(755) 6123-4567"
51
+ # number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/)
52
+ # # => "133-1234-5678"
43
53
  def number_to_phone(number, options = {})
44
54
  NumberToPhoneConverter.convert(number, options)
45
55
  end
@@ -47,6 +57,14 @@ module ActiveSupport
47
57
  # Formats a +number+ into a currency string (e.g., $13.65). You
48
58
  # can customize the format in the +options+ hash.
49
59
  #
60
+ # The currency unit and number formatting of the current locale will be used
61
+ # unless otherwise specified in the provided options. No currency conversion
62
+ # is performed. If the user is given a way to change their locale, they will
63
+ # also be able to change the relative value of the currency displayed with
64
+ # this helper. If your application will ever support multiple locales, you
65
+ # may want to specify a constant <tt>:locale</tt> option or consider
66
+ # using a library capable of currency conversion.
67
+ #
50
68
  # ==== Options
51
69
  #
52
70
  # * <tt>:locale</tt> - Sets the locale to be used for formatting
@@ -63,25 +81,25 @@ module ActiveSupport
63
81
  # (defaults to "%u%n"). Fields are <tt>%u</tt> for the
64
82
  # currency, and <tt>%n</tt> for the number.
65
83
  # * <tt>:negative_format</tt> - Sets the format for negative
66
- # numbers (defaults to prepending an hyphen to the formatted
84
+ # numbers (defaults to prepending a hyphen to the formatted
67
85
  # number given by <tt>:format</tt>). Accepts the same fields
68
86
  # than <tt>:format</tt>, except <tt>%n</tt> is here the
69
87
  # absolute value of the number.
70
88
  #
71
89
  # ==== Examples
72
90
  #
73
- # number_to_currency(1234567890.50) # => $1,234,567,890.50
74
- # number_to_currency(1234567890.506) # => $1,234,567,890.51
75
- # number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506
76
- # number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 €
77
- # number_to_currency('123a456') # => $123a456
91
+ # number_to_currency(1234567890.50) # => "$1,234,567,890.50"
92
+ # number_to_currency(1234567890.506) # => "$1,234,567,890.51"
93
+ # number_to_currency(1234567890.506, precision: 3) # => "$1,234,567,890.506"
94
+ # number_to_currency(1234567890.506, locale: :fr) # => "1 234 567 890,51 €"
95
+ # number_to_currency('123a456') # => "$123a456"
78
96
  #
79
97
  # number_to_currency(-1234567890.50, negative_format: '(%u%n)')
80
- # # => ($1,234,567,890.50)
98
+ # # => "($1,234,567,890.50)"
81
99
  # number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '')
82
- # # => &pound;1234567890,50
100
+ # # => "&pound;1234567890,50"
83
101
  # number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
84
- # # => 1234567890,50 &pound;
102
+ # # => "1234567890,50 &pound;"
85
103
  def number_to_currency(number, options = {})
86
104
  NumberToCurrencyConverter.convert(number, options)
87
105
  end
@@ -94,9 +112,9 @@ module ActiveSupport
94
112
  # * <tt>:locale</tt> - Sets the locale to be used for formatting
95
113
  # (defaults to current locale).
96
114
  # * <tt>:precision</tt> - Sets the precision of the number
97
- # (defaults to 3).
98
- # * <tt>:significant</tt> - If +true+, precision will be the #
99
- # of significant_digits. If +false+, the # of fractional
115
+ # (defaults to 3). Keeps the number's precision if +nil+.
116
+ # * <tt>:significant</tt> - If +true+, precision will be the number
117
+ # of significant_digits. If +false+, the number of fractional
100
118
  # digits (defaults to +false+).
101
119
  # * <tt>:separator</tt> - Sets the separator between the
102
120
  # fractional and integer digits (defaults to ".").
@@ -110,14 +128,15 @@ module ActiveSupport
110
128
  #
111
129
  # ==== Examples
112
130
  #
113
- # number_to_percentage(100) # => 100.000%
114
- # number_to_percentage('98') # => 98.000%
115
- # number_to_percentage(100, precision: 0) # => 100%
116
- # number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000%
117
- # number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
118
- # number_to_percentage(1000, locale: :fr) # => 1 000,000%
119
- # number_to_percentage('98a') # => 98a%
120
- # number_to_percentage(100, format: '%n %') # => 100 %
131
+ # number_to_percentage(100) # => "100.000%"
132
+ # number_to_percentage('98') # => "98.000%"
133
+ # number_to_percentage(100, precision: 0) # => "100%"
134
+ # number_to_percentage(1000, delimiter: '.', separator: ',') # => "1.000,000%"
135
+ # number_to_percentage(302.24398923423, precision: 5) # => "302.24399%"
136
+ # number_to_percentage(1000, locale: :fr) # => "1000,000%"
137
+ # number_to_percentage(1000, precision: nil) # => "1000%"
138
+ # number_to_percentage('98a') # => "98a%"
139
+ # number_to_percentage(100, format: '%n %') # => "100.000 %"
121
140
  def number_to_percentage(number, options = {})
122
141
  NumberToPercentageConverter.convert(number, options)
123
142
  end
@@ -134,19 +153,25 @@ module ActiveSupport
134
153
  # to ",").
135
154
  # * <tt>:separator</tt> - Sets the separator between the
136
155
  # fractional and integer digits (defaults to ".").
156
+ # * <tt>:delimiter_pattern</tt> - Sets a custom regular expression used for
157
+ # deriving the placement of delimiter. Helpful when using currency formats
158
+ # like INR.
137
159
  #
138
160
  # ==== Examples
139
161
  #
140
- # number_to_delimited(12345678) # => 12,345,678
141
- # number_to_delimited('123456') # => 123,456
142
- # number_to_delimited(12345678.05) # => 12,345,678.05
143
- # number_to_delimited(12345678, delimiter: '.') # => 12.345.678
144
- # number_to_delimited(12345678, delimiter: ',') # => 12,345,678
145
- # number_to_delimited(12345678.05, separator: ' ') # => 12,345,678 05
146
- # number_to_delimited(12345678.05, locale: :fr) # => 12 345 678,05
147
- # number_to_delimited('112a') # => 112a
162
+ # number_to_delimited(12345678) # => "12,345,678"
163
+ # number_to_delimited('123456') # => "123,456"
164
+ # number_to_delimited(12345678.05) # => "12,345,678.05"
165
+ # number_to_delimited(12345678, delimiter: '.') # => "12.345.678"
166
+ # number_to_delimited(12345678, delimiter: ',') # => "12,345,678"
167
+ # number_to_delimited(12345678.05, separator: ' ') # => "12,345,678 05"
168
+ # number_to_delimited(12345678.05, locale: :fr) # => "12 345 678,05"
169
+ # number_to_delimited('112a') # => "112a"
148
170
  # number_to_delimited(98765432.98, delimiter: ' ', separator: ',')
149
- # # => 98 765 432,98
171
+ # # => "98 765 432,98"
172
+ # number_to_delimited("123456.78",
173
+ # delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/)
174
+ # # => "1,23,456.78"
150
175
  def number_to_delimited(number, options = {})
151
176
  NumberToDelimitedConverter.convert(number, options)
152
177
  end
@@ -161,9 +186,9 @@ module ActiveSupport
161
186
  # * <tt>:locale</tt> - Sets the locale to be used for formatting
162
187
  # (defaults to current locale).
163
188
  # * <tt>:precision</tt> - Sets the precision of the number
164
- # (defaults to 3).
165
- # * <tt>:significant</tt> - If +true+, precision will be the #
166
- # of significant_digits. If +false+, the # of fractional
189
+ # (defaults to 3). Keeps the number's precision if +nil+.
190
+ # * <tt>:significant</tt> - If +true+, precision will be the number
191
+ # of significant_digits. If +false+, the number of fractional
167
192
  # digits (defaults to +false+).
168
193
  # * <tt>:separator</tt> - Sets the separator between the
169
194
  # fractional and integer digits (defaults to ".").
@@ -175,21 +200,22 @@ module ActiveSupport
175
200
  #
176
201
  # ==== Examples
177
202
  #
178
- # number_to_rounded(111.2345) # => 111.235
179
- # number_to_rounded(111.2345, precision: 2) # => 111.23
180
- # number_to_rounded(13, precision: 5) # => 13.00000
181
- # number_to_rounded(389.32314, precision: 0) # => 389
182
- # number_to_rounded(111.2345, significant: true) # => 111
183
- # number_to_rounded(111.2345, precision: 1, significant: true) # => 100
184
- # number_to_rounded(13, precision: 5, significant: true) # => 13.000
185
- # number_to_rounded(111.234, locale: :fr) # => 111,234
203
+ # number_to_rounded(111.2345) # => "111.235"
204
+ # number_to_rounded(111.2345, precision: 2) # => "111.23"
205
+ # number_to_rounded(13, precision: 5) # => "13.00000"
206
+ # number_to_rounded(389.32314, precision: 0) # => "389"
207
+ # number_to_rounded(111.2345, significant: true) # => "111"
208
+ # number_to_rounded(111.2345, precision: 1, significant: true) # => "100"
209
+ # number_to_rounded(13, precision: 5, significant: true) # => "13.000"
210
+ # number_to_rounded(13, precision: nil) # => "13"
211
+ # number_to_rounded(111.234, locale: :fr) # => "111,234"
186
212
  #
187
213
  # number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
188
- # # => 13
214
+ # # => "13"
189
215
  #
190
- # number_to_rounded(389.32314, precision: 4, significant: true) # => 389.3
216
+ # number_to_rounded(389.32314, precision: 4, significant: true) # => "389.3"
191
217
  # number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.')
192
- # # => 1.111,23
218
+ # # => "1.111,23"
193
219
  def number_to_rounded(number, options = {})
194
220
  NumberToRoundedConverter.convert(number, options)
195
221
  end
@@ -208,8 +234,8 @@ module ActiveSupport
208
234
  # (defaults to current locale).
209
235
  # * <tt>:precision</tt> - Sets the precision of the number
210
236
  # (defaults to 3).
211
- # * <tt>:significant</tt> - If +true+, precision will be the #
212
- # of significant_digits. If +false+, the # of fractional
237
+ # * <tt>:significant</tt> - If +true+, precision will be the number
238
+ # of significant_digits. If +false+, the number of fractional
213
239
  # digits (defaults to +true+)
214
240
  # * <tt>:separator</tt> - Sets the separator between the
215
241
  # fractional and integer digits (defaults to ".").
@@ -218,20 +244,20 @@ module ActiveSupport
218
244
  # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
219
245
  # insignificant zeros after the decimal separator (defaults to
220
246
  # +true+)
221
- # * <tt>:prefix</tt> - If +:si+ formats the number using the SI
222
- # prefix (defaults to :binary)
223
247
  #
224
248
  # ==== Examples
225
249
  #
226
- # number_to_human_size(123) # => 123 Bytes
227
- # number_to_human_size(1234) # => 1.21 KB
228
- # number_to_human_size(12345) # => 12.1 KB
229
- # number_to_human_size(1234567) # => 1.18 MB
230
- # number_to_human_size(1234567890) # => 1.15 GB
231
- # number_to_human_size(1234567890123) # => 1.12 TB
232
- # number_to_human_size(1234567, precision: 2) # => 1.2 MB
233
- # number_to_human_size(483989, precision: 2) # => 470 KB
234
- # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
250
+ # number_to_human_size(123) # => "123 Bytes"
251
+ # number_to_human_size(1234) # => "1.21 KB"
252
+ # number_to_human_size(12345) # => "12.1 KB"
253
+ # number_to_human_size(1234567) # => "1.18 MB"
254
+ # number_to_human_size(1234567890) # => "1.15 GB"
255
+ # number_to_human_size(1234567890123) # => "1.12 TB"
256
+ # number_to_human_size(1234567890123456) # => "1.1 PB"
257
+ # number_to_human_size(1234567890123456789) # => "1.07 EB"
258
+ # number_to_human_size(1234567, precision: 2) # => "1.2 MB"
259
+ # number_to_human_size(483989, precision: 2) # => "470 KB"
260
+ # number_to_human_size(1234567, precision: 2, separator: ',') # => "1,2 MB"
235
261
  # number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB"
236
262
  # number_to_human_size(524288000, precision: 5) # => "500 MB"
237
263
  def number_to_human_size(number, options = {})
@@ -258,8 +284,8 @@ module ActiveSupport
258
284
  # (defaults to current locale).
259
285
  # * <tt>:precision</tt> - Sets the precision of the number
260
286
  # (defaults to 3).
261
- # * <tt>:significant</tt> - If +true+, precision will be the #
262
- # of significant_digits. If +false+, the # of fractional
287
+ # * <tt>:significant</tt> - If +true+, precision will be the number
288
+ # of significant_digits. If +false+, the number of fractional
263
289
  # digits (defaults to +true+)
264
290
  # * <tt>:separator</tt> - Sets the separator between the
265
291
  # fractional and integer digits (defaults to ".").
@@ -1,8 +1,10 @@
1
- require 'active_support/core_ext/big_decimal/conversions'
2
- require 'active_support/core_ext/object/blank'
3
- require 'active_support/core_ext/hash/keys'
4
- require 'active_support/i18n'
5
- require 'active_support/core_ext/class/attribute'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/big_decimal/conversions"
4
+ require "active_support/core_ext/object/blank"
5
+ require "active_support/core_ext/hash/keys"
6
+ require "active_support/i18n"
7
+ require "active_support/core_ext/class/attribute"
6
8
 
7
9
  module ActiveSupport
8
10
  module NumberHelper
@@ -139,17 +141,17 @@ module ActiveSupport
139
141
  @options ||= format_options.merge(opts)
140
142
  end
141
143
 
142
- def format_options #:nodoc:
144
+ def format_options
143
145
  default_format_options.merge!(i18n_format_options)
144
146
  end
145
147
 
146
- def default_format_options #:nodoc:
148
+ def default_format_options
147
149
  options = DEFAULTS[:format].dup
148
150
  options.merge!(DEFAULTS[namespace][:format]) if namespace
149
151
  options
150
152
  end
151
153
 
152
- def i18n_format_options #:nodoc:
154
+ def i18n_format_options
153
155
  locale = opts[:locale]
154
156
  options = I18n.translate(:'number.format', locale: locale, default: {}).dup
155
157
 
@@ -160,7 +162,7 @@ module ActiveSupport
160
162
  options
161
163
  end
162
164
 
163
- def translate_number_value_with_default(key, i18n_options = {}) #:nodoc:
165
+ def translate_number_value_with_default(key, i18n_options = {})
164
166
  I18n.translate(key, { default: default_value(key), scope: :number }.merge!(i18n_options))
165
167
  end
166
168
 
@@ -169,10 +171,10 @@ module ActiveSupport
169
171
  end
170
172
 
171
173
  def default_value(key)
172
- key.split('.').reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
174
+ key.split(".").reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
173
175
  end
174
176
 
175
- def valid_float? #:nodoc:
177
+ def valid_float?
176
178
  Float(number)
177
179
  rescue ArgumentError, TypeError
178
180
  false
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/numeric/inquiry"
4
+
1
5
  module ActiveSupport
2
6
  module NumberHelper
3
7
  class NumberToCurrencyConverter < NumberConverter # :nodoc:
@@ -7,36 +11,32 @@ module ActiveSupport
7
11
  number = self.number.to_s.strip
8
12
  format = options[:format]
9
13
 
10
- if is_negative?(number)
14
+ if number.to_f.negative?
11
15
  format = options[:negative_format]
12
16
  number = absolute_value(number)
13
17
  end
14
18
 
15
19
  rounded_number = NumberToRoundedConverter.convert(number, options)
16
- format.gsub(/%n/, rounded_number).gsub(/%u/, options[:unit])
20
+ format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, options[:unit])
17
21
  end
18
22
 
19
23
  private
20
24
 
21
- def is_negative?(number)
22
- number.to_f.phase != 0
23
- end
24
-
25
25
  def absolute_value(number)
26
- number.respond_to?("abs") ? number.abs : number.sub(/\A-/, '')
26
+ number.respond_to?(:abs) ? number.abs : number.sub(/\A-/, "")
27
27
  end
28
28
 
29
29
  def options
30
30
  @options ||= begin
31
31
  defaults = default_format_options.merge(i18n_opts)
32
- # Override negative format if format options is given
32
+ # Override negative format if format options are given
33
33
  defaults[:negative_format] = "-#{opts[:format]}" if opts[:format]
34
34
  defaults.merge!(opts)
35
35
  end
36
36
  end
37
37
 
38
38
  def i18n_opts
39
- # Set International negative format if not exists
39
+ # Set International negative format if it does not exist
40
40
  i18n = i18n_format_options
41
41
  i18n[:negative_format] ||= "-#{i18n[:format]}" if i18n[:format]
42
42
  i18n
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module NumberHelper
3
5
  class NumberToDelimitedConverter < NumberConverter #:nodoc:
4
6
  self.validate_float = true
5
7
 
6
- DELIMITED_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
8
+ DEFAULT_DELIMITER_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
7
9
 
8
10
  def convert
9
11
  parts.join(options[:separator])
@@ -12,12 +14,16 @@ module ActiveSupport
12
14
  private
13
15
 
14
16
  def parts
15
- left, right = number.to_s.split('.')
16
- left.gsub!(DELIMITED_REGEX) do |digit_to_delimit|
17
+ left, right = number.to_s.split(".".freeze)
18
+ left.gsub!(delimiter_pattern) do |digit_to_delimit|
17
19
  "#{digit_to_delimit}#{options[:delimiter]}"
18
20
  end
19
21
  [left, right].compact
20
22
  end
23
+
24
+ def delimiter_pattern
25
+ options.fetch(:delimiter_pattern, DEFAULT_DELIMITER_REGEX)
26
+ end
21
27
  end
22
28
  end
23
29
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module NumberHelper
3
5
  class NumberToHumanConverter < NumberConverter # :nodoc:
@@ -9,6 +11,7 @@ module ActiveSupport
9
11
  self.validate_float = true
10
12
 
11
13
  def convert # :nodoc:
14
+ @number = RoundingHelper.new(options).round(number)
12
15
  @number = Float(number)
13
16
 
14
17
  # for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
@@ -18,27 +21,26 @@ module ActiveSupport
18
21
 
19
22
  units = opts[:units]
20
23
  exponent = calculate_exponent(units)
21
- @number = number / (10 ** exponent)
22
-
23
- unit = determine_unit(units, exponent)
24
+ @number = number / (10**exponent)
24
25
 
25
26
  rounded_number = NumberToRoundedConverter.convert(number, options)
26
- format.gsub(/%n/, rounded_number).gsub(/%u/, unit).strip
27
+ unit = determine_unit(units, exponent)
28
+ format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, unit).strip
27
29
  end
28
30
 
29
31
  private
30
32
 
31
33
  def format
32
- options[:format] || translate_in_locale('human.decimal_units.format')
34
+ options[:format] || translate_in_locale("human.decimal_units.format")
33
35
  end
34
36
 
35
37
  def determine_unit(units, exponent)
36
38
  exp = DECIMAL_UNITS[exponent]
37
39
  case units
38
40
  when Hash
39
- units[exp] || ''
41
+ units[exp] || ""
40
42
  when String, Symbol
41
- I18n.translate("#{units}.#{exp}", :locale => options[:locale], :count => number.to_i)
43
+ I18n.translate("#{units}.#{exp}", locale: options[:locale], count: number.to_i)
42
44
  else
43
45
  translate_in_locale("human.decimal_units.units.#{exp}", count: number.to_i)
44
46
  end
@@ -54,12 +56,12 @@ module ActiveSupport
54
56
  when Hash
55
57
  units
56
58
  when String, Symbol
57
- I18n.translate(units.to_s, :locale => options[:locale], :raise => true)
59
+ I18n.translate(units.to_s, locale: options[:locale], raise: true)
58
60
  when nil
59
61
  translate_in_locale("human.decimal_units.units", raise: true)
60
62
  else
61
63
  raise ArgumentError, ":units must be a Hash or String translation scope."
62
- end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by { |e| -e }
64
+ end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by(&:-@)
63
65
  end
64
66
  end
65
67
  end