activesupport 6.1.0 → 7.0.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.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +214 -382
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_support/actionable_error.rb +1 -1
  6. data/lib/active_support/array_inquirer.rb +0 -2
  7. data/lib/active_support/benchmarkable.rb +2 -2
  8. data/lib/active_support/cache/file_store.rb +16 -10
  9. data/lib/active_support/cache/mem_cache_store.rb +133 -34
  10. data/lib/active_support/cache/memory_store.rb +23 -15
  11. data/lib/active_support/cache/null_store.rb +10 -2
  12. data/lib/active_support/cache/redis_cache_store.rb +42 -67
  13. data/lib/active_support/cache/strategy/local_cache.rb +35 -61
  14. data/lib/active_support/cache.rb +196 -46
  15. data/lib/active_support/callbacks.rb +180 -81
  16. data/lib/active_support/code_generator.rb +65 -0
  17. data/lib/active_support/concern.rb +5 -5
  18. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  19. data/lib/active_support/concurrency/share_lock.rb +2 -2
  20. data/lib/active_support/configurable.rb +6 -3
  21. data/lib/active_support/configuration_file.rb +7 -2
  22. data/lib/active_support/core_ext/array/access.rb +1 -5
  23. data/lib/active_support/core_ext/array/conversions.rb +9 -7
  24. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  25. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  26. data/lib/active_support/core_ext/array.rb +1 -0
  27. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  28. data/lib/active_support/core_ext/class/subclasses.rb +4 -2
  29. data/lib/active_support/core_ext/date/blank.rb +1 -1
  30. data/lib/active_support/core_ext/date/calculations.rb +4 -4
  31. data/lib/active_support/core_ext/date/conversions.rb +3 -3
  32. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  33. data/lib/active_support/core_ext/date.rb +1 -0
  34. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  35. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  36. data/lib/active_support/core_ext/date_time/conversions.rb +5 -5
  37. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  38. data/lib/active_support/core_ext/date_time.rb +1 -0
  39. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  40. data/lib/active_support/core_ext/enumerable.rb +64 -12
  41. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  42. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  43. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  44. data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -0
  45. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +19 -10
  46. data/lib/active_support/core_ext/module/delegation.rb +2 -8
  47. data/lib/active_support/core_ext/name_error.rb +2 -8
  48. data/lib/active_support/core_ext/numeric/conversions.rb +79 -76
  49. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  50. data/lib/active_support/core_ext/numeric.rb +1 -0
  51. data/lib/active_support/core_ext/object/blank.rb +2 -2
  52. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  53. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  54. data/lib/active_support/core_ext/object/json.rb +36 -24
  55. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  56. data/lib/active_support/core_ext/object/try.rb +20 -20
  57. data/lib/active_support/core_ext/object/with_options.rb +20 -1
  58. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  59. data/lib/active_support/core_ext/pathname.rb +3 -0
  60. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  61. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  62. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  63. data/lib/active_support/core_ext/range/each.rb +1 -1
  64. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -25
  65. data/lib/active_support/core_ext/range.rb +1 -1
  66. data/lib/active_support/core_ext/string/filters.rb +1 -1
  67. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  68. data/lib/active_support/core_ext/string/output_safety.rb +61 -37
  69. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  70. data/lib/active_support/core_ext/time/calculations.rb +7 -5
  71. data/lib/active_support/core_ext/time/conversions.rb +5 -3
  72. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  73. data/lib/active_support/core_ext/time/zones.rb +4 -19
  74. data/lib/active_support/core_ext/time.rb +1 -0
  75. data/lib/active_support/core_ext/uri.rb +3 -27
  76. data/lib/active_support/core_ext.rb +2 -1
  77. data/lib/active_support/current_attributes.rb +32 -14
  78. data/lib/active_support/dependencies/interlock.rb +10 -18
  79. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  80. data/lib/active_support/dependencies.rb +58 -788
  81. data/lib/active_support/deprecation/behaviors.rb +4 -1
  82. data/lib/active_support/deprecation/method_wrappers.rb +3 -3
  83. data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
  84. data/lib/active_support/deprecation.rb +1 -1
  85. data/lib/active_support/descendants_tracker.rb +177 -68
  86. data/lib/active_support/digest.rb +5 -3
  87. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  88. data/lib/active_support/duration/iso8601_serializer.rb +9 -1
  89. data/lib/active_support/duration.rb +81 -51
  90. data/lib/active_support/encrypted_configuration.rb +11 -1
  91. data/lib/active_support/encrypted_file.rb +1 -1
  92. data/lib/active_support/environment_inquirer.rb +1 -1
  93. data/lib/active_support/error_reporter.rb +117 -0
  94. data/lib/active_support/evented_file_update_checker.rb +1 -1
  95. data/lib/active_support/execution_context/test_helper.rb +13 -0
  96. data/lib/active_support/execution_context.rb +53 -0
  97. data/lib/active_support/execution_wrapper.rb +30 -4
  98. data/lib/active_support/executor/test_helper.rb +7 -0
  99. data/lib/active_support/fork_tracker.rb +19 -10
  100. data/lib/active_support/gem_version.rb +2 -2
  101. data/lib/active_support/hash_with_indifferent_access.rb +9 -2
  102. data/lib/active_support/html_safe_translation.rb +43 -0
  103. data/lib/active_support/i18n.rb +1 -0
  104. data/lib/active_support/i18n_railtie.rb +1 -1
  105. data/lib/active_support/inflector/inflections.rb +23 -7
  106. data/lib/active_support/inflector/methods.rb +24 -48
  107. data/lib/active_support/isolated_execution_state.rb +56 -0
  108. data/lib/active_support/json/encoding.rb +3 -3
  109. data/lib/active_support/key_generator.rb +18 -1
  110. data/lib/active_support/locale/en.yml +2 -2
  111. data/lib/active_support/log_subscriber.rb +13 -3
  112. data/lib/active_support/logger_thread_safe_level.rb +4 -13
  113. data/lib/active_support/message_encryptor.rb +8 -3
  114. data/lib/active_support/message_verifier.rb +46 -14
  115. data/lib/active_support/messages/metadata.rb +2 -2
  116. data/lib/active_support/multibyte/chars.rb +10 -11
  117. data/lib/active_support/multibyte/unicode.rb +0 -12
  118. data/lib/active_support/multibyte.rb +1 -1
  119. data/lib/active_support/notifications/fanout.rb +91 -65
  120. data/lib/active_support/notifications/instrumenter.rb +32 -15
  121. data/lib/active_support/notifications.rb +16 -22
  122. data/lib/active_support/number_helper/number_converter.rb +1 -3
  123. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  124. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  125. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  126. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  127. data/lib/active_support/number_helper/number_to_rounded_converter.rb +10 -6
  128. data/lib/active_support/number_helper/rounding_helper.rb +2 -6
  129. data/lib/active_support/number_helper.rb +0 -2
  130. data/lib/active_support/option_merger.rb +8 -16
  131. data/lib/active_support/ordered_hash.rb +1 -1
  132. data/lib/active_support/parameter_filter.rb +6 -1
  133. data/lib/active_support/per_thread_registry.rb +5 -0
  134. data/lib/active_support/railtie.rb +69 -19
  135. data/lib/active_support/rescuable.rb +6 -6
  136. data/lib/active_support/ruby_features.rb +7 -0
  137. data/lib/active_support/secure_compare_rotator.rb +1 -1
  138. data/lib/active_support/security_utils.rb +1 -1
  139. data/lib/active_support/string_inquirer.rb +0 -2
  140. data/lib/active_support/subscriber.rb +7 -18
  141. data/lib/active_support/tagged_logging.rb +2 -2
  142. data/lib/active_support/test_case.rb +9 -21
  143. data/lib/active_support/testing/assertions.rb +35 -5
  144. data/lib/active_support/testing/deprecation.rb +52 -1
  145. data/lib/active_support/testing/isolation.rb +2 -2
  146. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  147. data/lib/active_support/testing/parallelization/server.rb +4 -0
  148. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  149. data/lib/active_support/testing/parallelization.rb +4 -0
  150. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  151. data/lib/active_support/testing/stream.rb +3 -5
  152. data/lib/active_support/testing/tagged_logging.rb +1 -1
  153. data/lib/active_support/testing/time_helpers.rb +13 -2
  154. data/lib/active_support/time_with_zone.rb +54 -13
  155. data/lib/active_support/values/time_zone.rb +31 -10
  156. data/lib/active_support/xml_mini/jdom.rb +1 -1
  157. data/lib/active_support/xml_mini/libxml.rb +5 -5
  158. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  159. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  160. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  161. data/lib/active_support/xml_mini/rexml.rb +1 -1
  162. data/lib/active_support/xml_mini.rb +5 -4
  163. data/lib/active_support.rb +17 -1
  164. metadata +26 -23
  165. data/lib/active_support/core_ext/marshal.rb +0 -26
  166. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -53,13 +53,7 @@ class NameError
53
53
  UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
54
54
  private_constant :UNBOUND_METHOD_MODULE_NAME
55
55
 
56
- if UnboundMethod.method_defined?(:bind_call)
57
- def real_mod_name(mod)
58
- UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
59
- end
60
- else
61
- def real_mod_name(mod)
62
- UNBOUND_METHOD_MODULE_NAME.bind(mod).call
63
- end
56
+ def real_mod_name(mod)
57
+ UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
64
58
  end
65
59
  end
@@ -9,6 +9,8 @@ module ActiveSupport
9
9
  # Options are provided for phone numbers, currency, percentage,
10
10
  # precision, positional notation, file size and pretty printing.
11
11
  #
12
+ # This method is aliased to <tt>to_fs</tt>.
13
+ #
12
14
  # ==== Options
13
15
  #
14
16
  # For details on which formats use which options, see ActiveSupport::NumberHelper
@@ -16,102 +18,102 @@ module ActiveSupport
16
18
  # ==== Examples
17
19
  #
18
20
  # Phone Numbers:
19
- # 5551234.to_s(:phone) # => "555-1234"
20
- # 1235551234.to_s(:phone) # => "123-555-1234"
21
- # 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234"
22
- # 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234"
23
- # 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
24
- # 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234"
25
- # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
21
+ # 5551234.to_formatted_s(:phone) # => "555-1234"
22
+ # 1235551234.to_formatted_s(:phone) # => "123-555-1234"
23
+ # 1235551234.to_formatted_s(:phone, area_code: true) # => "(123) 555-1234"
24
+ # 1235551234.to_formatted_s(:phone, delimiter: ' ') # => "123 555 1234"
25
+ # 1235551234.to_formatted_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
26
+ # 1235551234.to_formatted_s(:phone, country_code: 1) # => "+1-123-555-1234"
27
+ # 1235551234.to_formatted_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
26
28
  # # => "+1.123.555.1234 x 1343"
27
29
  #
28
30
  # Currency:
29
- # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
30
- # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
31
- # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
32
- # 1234567890.506.to_s(:currency, round_mode: :down) # => "$1,234,567,890.50"
33
- # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
34
- # -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
31
+ # 1234567890.50.to_formatted_s(:currency) # => "$1,234,567,890.50"
32
+ # 1234567890.506.to_formatted_s(:currency) # => "$1,234,567,890.51"
33
+ # 1234567890.506.to_formatted_s(:currency, precision: 3) # => "$1,234,567,890.506"
34
+ # 1234567890.506.to_formatted_s(:currency, round_mode: :down) # => "$1,234,567,890.50"
35
+ # 1234567890.506.to_formatted_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
36
+ # -1234567890.50.to_formatted_s(:currency, negative_format: '(%u%n)')
35
37
  # # => "($1,234,567,890.50)"
36
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
38
+ # 1234567890.50.to_formatted_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
37
39
  # # => "&pound;1234567890,50"
38
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
40
+ # 1234567890.50.to_formatted_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
39
41
  # # => "1234567890,50 &pound;"
40
42
  #
41
43
  # Percentage:
42
- # 100.to_s(:percentage) # => "100.000%"
43
- # 100.to_s(:percentage, precision: 0) # => "100%"
44
- # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
45
- # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
46
- # 302.24398923423.to_s(:percentage, round_mode: :down) # => "302.243%"
47
- # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
48
- # 100.to_s(:percentage, format: '%n %') # => "100.000 %"
44
+ # 100.to_formatted_s(:percentage) # => "100.000%"
45
+ # 100.to_formatted_s(:percentage, precision: 0) # => "100%"
46
+ # 1000.to_formatted_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
47
+ # 302.24398923423.to_formatted_s(:percentage, precision: 5) # => "302.24399%"
48
+ # 302.24398923423.to_formatted_s(:percentage, round_mode: :down) # => "302.243%"
49
+ # 1000.to_formatted_s(:percentage, locale: :fr) # => "1 000,000%"
50
+ # 100.to_formatted_s(:percentage, format: '%n %') # => "100.000 %"
49
51
  #
50
52
  # Delimited:
51
- # 12345678.to_s(:delimited) # => "12,345,678"
52
- # 12345678.05.to_s(:delimited) # => "12,345,678.05"
53
- # 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
54
- # 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
55
- # 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
56
- # 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
57
- # 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
53
+ # 12345678.to_formatted_s(:delimited) # => "12,345,678"
54
+ # 12345678.05.to_formatted_s(:delimited) # => "12,345,678.05"
55
+ # 12345678.to_formatted_s(:delimited, delimiter: '.') # => "12.345.678"
56
+ # 12345678.to_formatted_s(:delimited, delimiter: ',') # => "12,345,678"
57
+ # 12345678.05.to_formatted_s(:delimited, separator: ' ') # => "12,345,678 05"
58
+ # 12345678.05.to_formatted_s(:delimited, locale: :fr) # => "12 345 678,05"
59
+ # 98765432.98.to_formatted_s(:delimited, delimiter: ' ', separator: ',')
58
60
  # # => "98 765 432,98"
59
61
  #
60
62
  # Rounded:
61
- # 111.2345.to_s(:rounded) # => "111.235"
62
- # 111.2345.to_s(:rounded, precision: 2) # => "111.23"
63
- # 111.2345.to_s(:rounded, precision: 2, round_mode: :up) # => "111.24"
64
- # 13.to_s(:rounded, precision: 5) # => "13.00000"
65
- # 389.32314.to_s(:rounded, precision: 0) # => "389"
66
- # 111.2345.to_s(:rounded, significant: true) # => "111"
67
- # 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
68
- # 13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
69
- # 111.234.to_s(:rounded, locale: :fr) # => "111,234"
70
- # 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
63
+ # 111.2345.to_formatted_s(:rounded) # => "111.235"
64
+ # 111.2345.to_formatted_s(:rounded, precision: 2) # => "111.23"
65
+ # 111.2345.to_formatted_s(:rounded, precision: 2, round_mode: :up) # => "111.24"
66
+ # 13.to_formatted_s(:rounded, precision: 5) # => "13.00000"
67
+ # 389.32314.to_formatted_s(:rounded, precision: 0) # => "389"
68
+ # 111.2345.to_formatted_s(:rounded, significant: true) # => "111"
69
+ # 111.2345.to_formatted_s(:rounded, precision: 1, significant: true) # => "100"
70
+ # 13.to_formatted_s(:rounded, precision: 5, significant: true) # => "13.000"
71
+ # 111.234.to_formatted_s(:rounded, locale: :fr) # => "111,234"
72
+ # 13.to_formatted_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
71
73
  # # => "13"
72
- # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
73
- # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
74
+ # 389.32314.to_formatted_s(:rounded, precision: 4, significant: true) # => "389.3"
75
+ # 1111.2345.to_formatted_s(:rounded, precision: 2, separator: ',', delimiter: '.')
74
76
  # # => "1.111,23"
75
77
  #
76
78
  # Human-friendly size in Bytes:
77
- # 123.to_s(:human_size) # => "123 Bytes"
78
- # 1234.to_s(:human_size) # => "1.21 KB"
79
- # 12345.to_s(:human_size) # => "12.1 KB"
80
- # 1234567.to_s(:human_size) # => "1.18 MB"
81
- # 1234567890.to_s(:human_size) # => "1.15 GB"
82
- # 1234567890123.to_s(:human_size) # => "1.12 TB"
83
- # 1234567890123456.to_s(:human_size) # => "1.1 PB"
84
- # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
85
- # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
86
- # 1234567.to_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
87
- # 483989.to_s(:human_size, precision: 2) # => "470 KB"
88
- # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
89
- # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
90
- # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
79
+ # 123.to_formatted_s(:human_size) # => "123 Bytes"
80
+ # 1234.to_formatted_s(:human_size) # => "1.21 KB"
81
+ # 12345.to_formatted_s(:human_size) # => "12.1 KB"
82
+ # 1234567.to_formatted_s(:human_size) # => "1.18 MB"
83
+ # 1234567890.to_formatted_s(:human_size) # => "1.15 GB"
84
+ # 1234567890123.to_formatted_s(:human_size) # => "1.12 TB"
85
+ # 1234567890123456.to_formatted_s(:human_size) # => "1.1 PB"
86
+ # 1234567890123456789.to_formatted_s(:human_size) # => "1.07 EB"
87
+ # 1234567.to_formatted_s(:human_size, precision: 2) # => "1.2 MB"
88
+ # 1234567.to_formatted_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
89
+ # 483989.to_formatted_s(:human_size, precision: 2) # => "470 KB"
90
+ # 1234567.to_formatted_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
91
+ # 1234567890123.to_formatted_s(:human_size, precision: 5) # => "1.1228 TB"
92
+ # 524288000.to_formatted_s(:human_size, precision: 5) # => "500 MB"
91
93
  #
92
94
  # Human-friendly format:
93
- # 123.to_s(:human) # => "123"
94
- # 1234.to_s(:human) # => "1.23 Thousand"
95
- # 12345.to_s(:human) # => "12.3 Thousand"
96
- # 1234567.to_s(:human) # => "1.23 Million"
97
- # 1234567890.to_s(:human) # => "1.23 Billion"
98
- # 1234567890123.to_s(:human) # => "1.23 Trillion"
99
- # 1234567890123456.to_s(:human) # => "1.23 Quadrillion"
100
- # 1234567890123456789.to_s(:human) # => "1230 Quadrillion"
101
- # 489939.to_s(:human, precision: 2) # => "490 Thousand"
102
- # 489939.to_s(:human, precision: 2, round_mode: :down) # => "480 Thousand"
103
- # 489939.to_s(:human, precision: 4) # => "489.9 Thousand"
104
- # 1234567.to_s(:human, precision: 4,
105
- # significant: false) # => "1.2346 Million"
106
- # 1234567.to_s(:human, precision: 1,
95
+ # 123.to_formatted_s(:human) # => "123"
96
+ # 1234.to_formatted_s(:human) # => "1.23 Thousand"
97
+ # 12345.to_formatted_s(:human) # => "12.3 Thousand"
98
+ # 1234567.to_formatted_s(:human) # => "1.23 Million"
99
+ # 1234567890.to_formatted_s(:human) # => "1.23 Billion"
100
+ # 1234567890123.to_formatted_s(:human) # => "1.23 Trillion"
101
+ # 1234567890123456.to_formatted_s(:human) # => "1.23 Quadrillion"
102
+ # 1234567890123456789.to_formatted_s(:human) # => "1230 Quadrillion"
103
+ # 489939.to_formatted_s(:human, precision: 2) # => "490 Thousand"
104
+ # 489939.to_formatted_s(:human, precision: 2, round_mode: :down) # => "480 Thousand"
105
+ # 489939.to_formatted_s(:human, precision: 4) # => "489.9 Thousand"
106
+ # 1234567.to_formatted_s(:human, precision: 4,
107
+ # significant: false) # => "1.2346 Million"
108
+ # 1234567.to_formatted_s(:human, precision: 1,
107
109
  # separator: ',',
108
- # significant: false) # => "1,2 Million"
109
- def to_s(format = nil, options = nil)
110
+ # significant: false) # => "1,2 Million"
111
+ def to_formatted_s(format = nil, options = nil)
112
+ return to_s if format.nil?
113
+
110
114
  case format
111
- when nil
112
- super()
113
115
  when Integer, String
114
- super(format)
116
+ to_s(format)
115
117
  when :phone
116
118
  ActiveSupport::NumberHelper.number_to_phone(self, options || {})
117
119
  when :currency
@@ -127,11 +129,12 @@ module ActiveSupport
127
129
  when :human_size
128
130
  ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
129
131
  when Symbol
130
- super()
132
+ to_s
131
133
  else
132
- super(format)
134
+ to_s(format)
133
135
  end
134
136
  end
137
+ alias_method :to_fs, :to_formatted_s
135
138
  end
136
139
  end
137
140
 
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module DeprecatedNumericWithFormat # :nodoc:
5
+ def to_s(format = nil, options = nil)
6
+ return super() if format.nil?
7
+
8
+ case format
9
+ when Integer, String
10
+ super(format)
11
+ when :phone
12
+ ActiveSupport::Deprecation.warn(
13
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
14
+ )
15
+ ActiveSupport::NumberHelper.number_to_phone(self, options || {})
16
+ when :currency
17
+ ActiveSupport::Deprecation.warn(
18
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
19
+ )
20
+ ActiveSupport::NumberHelper.number_to_currency(self, options || {})
21
+ when :percentage
22
+ ActiveSupport::Deprecation.warn(
23
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
24
+ )
25
+ ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
26
+ when :delimited
27
+ ActiveSupport::Deprecation.warn(
28
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
29
+ )
30
+ ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
31
+ when :rounded
32
+ ActiveSupport::Deprecation.warn(
33
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
34
+ )
35
+ ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
36
+ when :human
37
+ ActiveSupport::Deprecation.warn(
38
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
39
+ )
40
+ ActiveSupport::NumberHelper.number_to_human(self, options || {})
41
+ when :human_size
42
+ ActiveSupport::Deprecation.warn(
43
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
44
+ )
45
+ ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
46
+ when Symbol
47
+ ActiveSupport::Deprecation.warn(
48
+ "#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
49
+ )
50
+ super()
51
+ else
52
+ super(format)
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ Integer.prepend ActiveSupport::DeprecatedNumericWithFormat
59
+ Float.prepend ActiveSupport::DeprecatedNumericWithFormat
60
+ BigDecimal.prepend ActiveSupport::DeprecatedNumericWithFormat
@@ -3,3 +3,4 @@
3
3
  require "active_support/core_ext/numeric/bytes"
4
4
  require "active_support/core_ext/numeric/time"
5
5
  require "active_support/core_ext/numeric/conversions"
6
+ require "active_support/core_ext/numeric/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
@@ -131,7 +131,7 @@ class String
131
131
  end
132
132
  end
133
133
 
134
- class Numeric #:nodoc:
134
+ class Numeric # :nodoc:
135
135
  # No number is blank:
136
136
  #
137
137
  # 1.blank? # => false
@@ -143,7 +143,7 @@ class Numeric #:nodoc:
143
143
  end
144
144
  end
145
145
 
146
- class Time #:nodoc:
146
+ class Time # :nodoc:
147
147
  # No Time is blank:
148
148
  #
149
149
  # Time.now.blank? # => false
@@ -43,7 +43,7 @@ class Hash
43
43
  def deep_dup
44
44
  hash = dup
45
45
  each_pair do |key, value|
46
- if (::String === key && key.frozen?) || ::Symbol === key
46
+ if ::String === key || ::Symbol === key
47
47
  hash[key] = value.deep_dup
48
48
  else
49
49
  hash.delete(key)
@@ -47,3 +47,14 @@ class UnboundMethod
47
47
  false
48
48
  end
49
49
  end
50
+
51
+ require "singleton"
52
+
53
+ module Singleton
54
+ # Singleton instances are not duplicable:
55
+ #
56
+ # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
57
+ def duplicable?
58
+ false
59
+ end
60
+ end
@@ -3,6 +3,7 @@
3
3
  # Hack to load json gem first so we can overwrite its to_json.
4
4
  require "json"
5
5
  require "bigdecimal"
6
+ require "ipaddr"
6
7
  require "uri/generic"
7
8
  require "pathname"
8
9
  require "active_support/core_ext/big_decimal/conversions" # for #to_s
@@ -18,8 +19,7 @@ require "active_support/core_ext/date/conversions"
18
19
  # The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
19
20
  # their default behavior. That said, we need to define the basic to_json method in all of them,
20
21
  # otherwise they will always use to_json gem implementation, which is backwards incompatible in
21
- # several cases (for instance, the JSON implementation for Hash does not work) with inheritance
22
- # and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
22
+ # several cases (for instance, the JSON implementation for Hash does not work) with inheritance.
23
23
  #
24
24
  # On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
25
25
  # JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
@@ -49,8 +49,14 @@ end
49
49
  klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
50
50
  end
51
51
 
52
+ class Module
53
+ def as_json(options = nil) # :nodoc:
54
+ name
55
+ end
56
+ end
57
+
52
58
  class Object
53
- def as_json(options = nil) #:nodoc:
59
+ def as_json(options = nil) # :nodoc:
54
60
  if respond_to?(:to_hash)
55
61
  to_hash.as_json(options)
56
62
  else
@@ -59,44 +65,44 @@ class Object
59
65
  end
60
66
  end
61
67
 
62
- class Struct #:nodoc:
68
+ class Struct # :nodoc:
63
69
  def as_json(options = nil)
64
70
  Hash[members.zip(values)].as_json(options)
65
71
  end
66
72
  end
67
73
 
68
74
  class TrueClass
69
- def as_json(options = nil) #:nodoc:
75
+ def as_json(options = nil) # :nodoc:
70
76
  self
71
77
  end
72
78
  end
73
79
 
74
80
  class FalseClass
75
- def as_json(options = nil) #:nodoc:
81
+ def as_json(options = nil) # :nodoc:
76
82
  self
77
83
  end
78
84
  end
79
85
 
80
86
  class NilClass
81
- def as_json(options = nil) #:nodoc:
87
+ def as_json(options = nil) # :nodoc:
82
88
  self
83
89
  end
84
90
  end
85
91
 
86
92
  class String
87
- def as_json(options = nil) #:nodoc:
93
+ def as_json(options = nil) # :nodoc:
88
94
  self
89
95
  end
90
96
  end
91
97
 
92
98
  class Symbol
93
- def as_json(options = nil) #:nodoc:
99
+ def as_json(options = nil) # :nodoc:
94
100
  to_s
95
101
  end
96
102
  end
97
103
 
98
104
  class Numeric
99
- def as_json(options = nil) #:nodoc:
105
+ def as_json(options = nil) # :nodoc:
100
106
  self
101
107
  end
102
108
  end
@@ -104,7 +110,7 @@ end
104
110
  class Float
105
111
  # Encoding Infinity or NaN to JSON should return "null". The default returns
106
112
  # "Infinity" or "NaN" which are not valid JSON.
107
- def as_json(options = nil) #:nodoc:
113
+ def as_json(options = nil) # :nodoc:
108
114
  finite? ? self : nil
109
115
  end
110
116
  end
@@ -119,43 +125,43 @@ class BigDecimal
119
125
  # if the other end knows by contract that the data is supposed to be a
120
126
  # BigDecimal, it still has the chance to post-process the string and get the
121
127
  # real value.
122
- def as_json(options = nil) #:nodoc:
128
+ def as_json(options = nil) # :nodoc:
123
129
  finite? ? to_s : nil
124
130
  end
125
131
  end
126
132
 
127
133
  class Regexp
128
- def as_json(options = nil) #:nodoc:
134
+ def as_json(options = nil) # :nodoc:
129
135
  to_s
130
136
  end
131
137
  end
132
138
 
133
139
  module Enumerable
134
- def as_json(options = nil) #:nodoc:
140
+ def as_json(options = nil) # :nodoc:
135
141
  to_a.as_json(options)
136
142
  end
137
143
  end
138
144
 
139
145
  class IO
140
- def as_json(options = nil) #:nodoc:
146
+ def as_json(options = nil) # :nodoc:
141
147
  to_s
142
148
  end
143
149
  end
144
150
 
145
151
  class Range
146
- def as_json(options = nil) #:nodoc:
152
+ def as_json(options = nil) # :nodoc:
147
153
  to_s
148
154
  end
149
155
  end
150
156
 
151
157
  class Array
152
- def as_json(options = nil) #:nodoc:
158
+ def as_json(options = nil) # :nodoc:
153
159
  map { |v| options ? v.as_json(options.dup) : v.as_json }
154
160
  end
155
161
  end
156
162
 
157
163
  class Hash
158
- def as_json(options = nil) #:nodoc:
164
+ def as_json(options = nil) # :nodoc:
159
165
  # create a subset of the hash by applying :only or :except
160
166
  subset = if options
161
167
  if attrs = options[:only]
@@ -178,7 +184,7 @@ class Hash
178
184
  end
179
185
 
180
186
  class Time
181
- def as_json(options = nil) #:nodoc:
187
+ def as_json(options = nil) # :nodoc:
182
188
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
183
189
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
184
190
  else
@@ -188,7 +194,7 @@ class Time
188
194
  end
189
195
 
190
196
  class Date
191
- def as_json(options = nil) #:nodoc:
197
+ def as_json(options = nil) # :nodoc:
192
198
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
193
199
  strftime("%Y-%m-%d")
194
200
  else
@@ -198,7 +204,7 @@ class Date
198
204
  end
199
205
 
200
206
  class DateTime
201
- def as_json(options = nil) #:nodoc:
207
+ def as_json(options = nil) # :nodoc:
202
208
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
203
209
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
204
210
  else
@@ -207,19 +213,25 @@ class DateTime
207
213
  end
208
214
  end
209
215
 
210
- class URI::Generic #:nodoc:
216
+ class URI::Generic # :nodoc:
217
+ def as_json(options = nil)
218
+ to_s
219
+ end
220
+ end
221
+
222
+ class Pathname # :nodoc:
211
223
  def as_json(options = nil)
212
224
  to_s
213
225
  end
214
226
  end
215
227
 
216
- class Pathname #:nodoc:
228
+ class IPAddr # :nodoc:
217
229
  def as_json(options = nil)
218
230
  to_s
219
231
  end
220
232
  end
221
233
 
222
- class Process::Status #:nodoc:
234
+ class Process::Status # :nodoc:
223
235
  def as_json(options = nil)
224
236
  { exitstatus: exitstatus, pid: pid }
225
237
  end
@@ -75,11 +75,11 @@ class Hash
75
75
  #
76
76
  # This method is also aliased as +to_param+.
77
77
  def to_query(namespace = nil)
78
- query = collect do |key, value|
78
+ query = filter_map do |key, value|
79
79
  unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
80
80
  value.to_query(namespace ? "#{namespace}[#{key}]" : key)
81
81
  end
82
- end.compact
82
+ end
83
83
 
84
84
  query.sort! unless namespace.to_s.include?("[]")
85
85
  query.join("&")
@@ -3,32 +3,32 @@
3
3
  require "delegate"
4
4
 
5
5
  module ActiveSupport
6
- module Tryable #:nodoc:
7
- def try(method_name = nil, *args, &b)
8
- if method_name.nil? && block_given?
9
- if b.arity == 0
10
- instance_eval(&b)
6
+ module Tryable # :nodoc:
7
+ def try(*args, &block)
8
+ if args.empty? && block_given?
9
+ if block.arity == 0
10
+ instance_eval(&block)
11
11
  else
12
12
  yield self
13
13
  end
14
- elsif respond_to?(method_name)
15
- public_send(method_name, *args, &b)
14
+ elsif respond_to?(args.first)
15
+ public_send(*args, &block)
16
16
  end
17
17
  end
18
- ruby2_keywords(:try) if respond_to?(:ruby2_keywords, true)
18
+ ruby2_keywords(:try)
19
19
 
20
- def try!(method_name = nil, *args, &b)
21
- if method_name.nil? && block_given?
22
- if b.arity == 0
23
- instance_eval(&b)
20
+ def try!(*args, &block)
21
+ if args.empty? && block_given?
22
+ if block.arity == 0
23
+ instance_eval(&block)
24
24
  else
25
25
  yield self
26
26
  end
27
27
  else
28
- public_send(method_name, *args, &b)
28
+ public_send(*args, &block)
29
29
  end
30
30
  end
31
- ruby2_keywords(:try!) if respond_to?(:ruby2_keywords, true)
31
+ ruby2_keywords(:try!)
32
32
  end
33
33
  end
34
34
 
@@ -39,7 +39,7 @@ class Object
39
39
  # :method: try
40
40
  #
41
41
  # :call-seq:
42
- # try(*a, &b)
42
+ # try(*args, &block)
43
43
  #
44
44
  # Invokes the public method whose name goes as first argument just like
45
45
  # +public_send+ does, except that if the receiver does not respond to it the
@@ -104,7 +104,7 @@ class Object
104
104
  # :method: try!
105
105
  #
106
106
  # :call-seq:
107
- # try!(*a, &b)
107
+ # try!(*args, &block)
108
108
  #
109
109
  # Same as #try, but raises a +NoMethodError+ exception if the receiver is
110
110
  # not +nil+ and does not implement the tried method.
@@ -121,7 +121,7 @@ class Delegator
121
121
  # :method: try
122
122
  #
123
123
  # :call-seq:
124
- # try(a*, &b)
124
+ # try(*args, &block)
125
125
  #
126
126
  # See Object#try
127
127
 
@@ -129,7 +129,7 @@ class Delegator
129
129
  # :method: try!
130
130
  #
131
131
  # :call-seq:
132
- # try!(a*, &b)
132
+ # try!(*args, &block)
133
133
  #
134
134
  # See Object#try!
135
135
  end
@@ -145,14 +145,14 @@ class NilClass
145
145
  #
146
146
  # With +try+
147
147
  # @person.try(:children).try(:first).try(:name)
148
- def try(_method_name = nil, *)
148
+ def try(*)
149
149
  nil
150
150
  end
151
151
 
152
152
  # Calling +try!+ on +nil+ always returns +nil+.
153
153
  #
154
154
  # nil.try!(:name) # => nil
155
- def try!(_method_name = nil, *)
155
+ def try!(*)
156
156
  nil
157
157
  end
158
158
  end