activesupport 6.1.7.2 → 7.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (222) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +866 -411
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +4 -2
  6. data/lib/active_support/array_inquirer.rb +2 -2
  7. data/lib/active_support/backtrace_cleaner.rb +27 -7
  8. data/lib/active_support/benchmarkable.rb +3 -2
  9. data/lib/active_support/broadcast_logger.rb +250 -0
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache/coder.rb +153 -0
  12. data/lib/active_support/cache/entry.rb +134 -0
  13. data/lib/active_support/cache/file_store.rb +52 -19
  14. data/lib/active_support/cache/mem_cache_store.rb +195 -60
  15. data/lib/active_support/cache/memory_store.rb +86 -24
  16. data/lib/active_support/cache/null_store.rb +16 -2
  17. data/lib/active_support/cache/redis_cache_store.rb +186 -193
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +63 -71
  20. data/lib/active_support/cache.rb +478 -247
  21. data/lib/active_support/callbacks.rb +227 -105
  22. data/lib/active_support/code_generator.rb +65 -0
  23. data/lib/active_support/concern.rb +9 -7
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/concurrency/share_lock.rb +2 -2
  27. data/lib/active_support/configurable.rb +18 -5
  28. data/lib/active_support/configuration_file.rb +1 -1
  29. data/lib/active_support/core_ext/array/access.rb +1 -5
  30. data/lib/active_support/core_ext/array/conversions.rb +15 -13
  31. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  33. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  34. data/lib/active_support/core_ext/class/subclasses.rb +37 -26
  35. data/lib/active_support/core_ext/date/blank.rb +1 -1
  36. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  37. data/lib/active_support/core_ext/date/conversions.rb +16 -15
  38. data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
  39. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  40. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  41. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  42. data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
  43. data/lib/active_support/core_ext/digest/uuid.rb +30 -14
  44. data/lib/active_support/core_ext/enumerable.rb +85 -83
  45. data/lib/active_support/core_ext/erb/util.rb +196 -0
  46. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  47. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  48. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  49. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  50. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  51. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  52. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  53. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  54. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  55. data/lib/active_support/core_ext/module/attribute_accessors.rb +8 -0
  56. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +49 -22
  57. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  58. data/lib/active_support/core_ext/module/delegation.rb +41 -18
  59. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  60. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  61. data/lib/active_support/core_ext/name_error.rb +2 -8
  62. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  63. data/lib/active_support/core_ext/numeric/conversions.rb +82 -77
  64. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  65. data/lib/active_support/core_ext/object/blank.rb +2 -2
  66. data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
  67. data/lib/active_support/core_ext/object/duplicable.rb +15 -4
  68. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  69. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  70. data/lib/active_support/core_ext/object/json.rb +40 -27
  71. data/lib/active_support/core_ext/object/to_query.rb +2 -4
  72. data/lib/active_support/core_ext/object/try.rb +20 -20
  73. data/lib/active_support/core_ext/object/with.rb +44 -0
  74. data/lib/active_support/core_ext/object/with_options.rb +25 -6
  75. data/lib/active_support/core_ext/object.rb +1 -0
  76. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  77. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  78. data/lib/active_support/core_ext/pathname.rb +4 -0
  79. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  80. data/lib/active_support/core_ext/range/conversions.rb +34 -13
  81. data/lib/active_support/core_ext/range/each.rb +1 -1
  82. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  83. data/lib/active_support/core_ext/range.rb +1 -2
  84. data/lib/active_support/core_ext/securerandom.rb +25 -13
  85. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  86. data/lib/active_support/core_ext/string/filters.rb +21 -15
  87. data/lib/active_support/core_ext/string/indent.rb +1 -1
  88. data/lib/active_support/core_ext/string/inflections.rb +17 -10
  89. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  90. data/lib/active_support/core_ext/string/output_safety.rb +85 -193
  91. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  92. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  93. data/lib/active_support/core_ext/time/calculations.rb +29 -10
  94. data/lib/active_support/core_ext/time/conversions.rb +14 -13
  95. data/lib/active_support/core_ext/time/zones.rb +12 -28
  96. data/lib/active_support/core_ext.rb +1 -0
  97. data/lib/active_support/current_attributes.rb +46 -21
  98. data/lib/active_support/deep_mergeable.rb +53 -0
  99. data/lib/active_support/dependencies/autoload.rb +17 -12
  100. data/lib/active_support/dependencies/interlock.rb +10 -18
  101. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  102. data/lib/active_support/dependencies.rb +58 -788
  103. data/lib/active_support/deprecation/behaviors.rb +66 -40
  104. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  105. data/lib/active_support/deprecation/deprecators.rb +104 -0
  106. data/lib/active_support/deprecation/disallowed.rb +6 -8
  107. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  108. data/lib/active_support/deprecation/method_wrappers.rb +9 -26
  109. data/lib/active_support/deprecation/proxy_wrappers.rb +38 -23
  110. data/lib/active_support/deprecation/reporting.rb +42 -25
  111. data/lib/active_support/deprecation.rb +32 -5
  112. data/lib/active_support/deprecator.rb +7 -0
  113. data/lib/active_support/descendants_tracker.rb +150 -72
  114. data/lib/active_support/digest.rb +4 -4
  115. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  116. data/lib/active_support/duration/iso8601_serializer.rb +9 -3
  117. data/lib/active_support/duration.rb +79 -49
  118. data/lib/active_support/encrypted_configuration.rb +72 -9
  119. data/lib/active_support/encrypted_file.rb +29 -13
  120. data/lib/active_support/environment_inquirer.rb +23 -3
  121. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  122. data/lib/active_support/error_reporter.rb +203 -0
  123. data/lib/active_support/evented_file_update_checker.rb +20 -7
  124. data/lib/active_support/execution_context/test_helper.rb +13 -0
  125. data/lib/active_support/execution_context.rb +53 -0
  126. data/lib/active_support/execution_wrapper.rb +31 -12
  127. data/lib/active_support/executor/test_helper.rb +7 -0
  128. data/lib/active_support/file_update_checker.rb +4 -2
  129. data/lib/active_support/fork_tracker.rb +28 -13
  130. data/lib/active_support/gem_version.rb +4 -4
  131. data/lib/active_support/gzip.rb +2 -0
  132. data/lib/active_support/hash_with_indifferent_access.rb +38 -18
  133. data/lib/active_support/html_safe_translation.rb +43 -0
  134. data/lib/active_support/i18n.rb +2 -1
  135. data/lib/active_support/i18n_railtie.rb +21 -14
  136. data/lib/active_support/inflector/inflections.rb +25 -7
  137. data/lib/active_support/inflector/methods.rb +50 -63
  138. data/lib/active_support/inflector/transliterate.rb +4 -2
  139. data/lib/active_support/isolated_execution_state.rb +76 -0
  140. data/lib/active_support/json/decoding.rb +2 -1
  141. data/lib/active_support/json/encoding.rb +27 -45
  142. data/lib/active_support/key_generator.rb +31 -6
  143. data/lib/active_support/lazy_load_hooks.rb +33 -7
  144. data/lib/active_support/locale/en.yml +3 -1
  145. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  146. data/lib/active_support/log_subscriber.rb +96 -35
  147. data/lib/active_support/logger.rb +9 -60
  148. data/lib/active_support/logger_thread_safe_level.rb +11 -34
  149. data/lib/active_support/message_encryptor.rb +206 -56
  150. data/lib/active_support/message_encryptors.rb +141 -0
  151. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  152. data/lib/active_support/message_pack/extensions.rb +292 -0
  153. data/lib/active_support/message_pack/serializer.rb +63 -0
  154. data/lib/active_support/message_pack.rb +50 -0
  155. data/lib/active_support/message_verifier.rb +235 -84
  156. data/lib/active_support/message_verifiers.rb +135 -0
  157. data/lib/active_support/messages/codec.rb +65 -0
  158. data/lib/active_support/messages/metadata.rb +112 -46
  159. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  160. data/lib/active_support/messages/rotator.rb +34 -32
  161. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  162. data/lib/active_support/multibyte/chars.rb +12 -11
  163. data/lib/active_support/multibyte/unicode.rb +9 -49
  164. data/lib/active_support/multibyte.rb +1 -1
  165. data/lib/active_support/notifications/fanout.rb +304 -114
  166. data/lib/active_support/notifications/instrumenter.rb +109 -35
  167. data/lib/active_support/notifications.rb +24 -24
  168. data/lib/active_support/number_helper/number_converter.rb +14 -7
  169. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  170. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  171. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -4
  172. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  173. data/lib/active_support/number_helper/rounding_helper.rb +1 -5
  174. data/lib/active_support/number_helper.rb +379 -319
  175. data/lib/active_support/option_merger.rb +10 -18
  176. data/lib/active_support/ordered_hash.rb +4 -4
  177. data/lib/active_support/ordered_options.rb +15 -1
  178. data/lib/active_support/parameter_filter.rb +104 -80
  179. data/lib/active_support/proxy_object.rb +2 -0
  180. data/lib/active_support/railtie.rb +83 -21
  181. data/lib/active_support/reloader.rb +12 -4
  182. data/lib/active_support/rescuable.rb +14 -12
  183. data/lib/active_support/ruby_features.rb +7 -0
  184. data/lib/active_support/secure_compare_rotator.rb +18 -11
  185. data/lib/active_support/string_inquirer.rb +3 -3
  186. data/lib/active_support/subscriber.rb +11 -40
  187. data/lib/active_support/syntax_error_proxy.rb +70 -0
  188. data/lib/active_support/tagged_logging.rb +60 -24
  189. data/lib/active_support/test_case.rb +166 -27
  190. data/lib/active_support/testing/assertions.rb +60 -14
  191. data/lib/active_support/testing/autorun.rb +0 -2
  192. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  193. data/lib/active_support/testing/deprecation.rb +53 -2
  194. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  195. data/lib/active_support/testing/isolation.rb +30 -29
  196. data/lib/active_support/testing/method_call_assertions.rb +24 -11
  197. data/lib/active_support/testing/parallelization/server.rb +4 -0
  198. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  199. data/lib/active_support/testing/parallelization.rb +4 -0
  200. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  201. data/lib/active_support/testing/stream.rb +4 -6
  202. data/lib/active_support/testing/strict_warnings.rb +39 -0
  203. data/lib/active_support/testing/tagged_logging.rb +1 -1
  204. data/lib/active_support/testing/time_helpers.rb +49 -16
  205. data/lib/active_support/time_with_zone.rb +39 -28
  206. data/lib/active_support/values/time_zone.rb +38 -17
  207. data/lib/active_support/version.rb +1 -1
  208. data/lib/active_support/xml_mini/jdom.rb +4 -11
  209. data/lib/active_support/xml_mini/libxml.rb +5 -5
  210. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  211. data/lib/active_support/xml_mini/nokogiri.rb +5 -5
  212. data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
  213. data/lib/active_support/xml_mini/rexml.rb +2 -2
  214. data/lib/active_support/xml_mini.rb +7 -6
  215. data/lib/active_support.rb +28 -1
  216. metadata +107 -18
  217. data/lib/active_support/core_ext/marshal.rb +0 -26
  218. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
  219. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  220. data/lib/active_support/core_ext/uri.rb +0 -29
  221. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
  222. data/lib/active_support/per_thread_registry.rb +0 -61
@@ -5,9 +5,13 @@ require "active_support/number_helper"
5
5
 
6
6
  module ActiveSupport
7
7
  module NumericWithFormat
8
+ # \Numeric With Format
9
+ #
8
10
  # Provides options for converting numbers into formatted strings.
9
11
  # Options are provided for phone numbers, currency, percentage,
10
- # precision, positional notation, file size and pretty printing.
12
+ # precision, positional notation, file size, and pretty printing.
13
+ #
14
+ # This method is aliased to <tt>to_formatted_s</tt>.
11
15
  #
12
16
  # ==== Options
13
17
  #
@@ -16,102 +20,102 @@ module ActiveSupport
16
20
  # ==== Examples
17
21
  #
18
22
  # 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: '.')
23
+ # 5551234.to_fs(:phone) # => "555-1234"
24
+ # 1235551234.to_fs(:phone) # => "123-555-1234"
25
+ # 1235551234.to_fs(:phone, area_code: true) # => "(123) 555-1234"
26
+ # 1235551234.to_fs(:phone, delimiter: ' ') # => "123 555 1234"
27
+ # 1235551234.to_fs(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
28
+ # 1235551234.to_fs(:phone, country_code: 1) # => "+1-123-555-1234"
29
+ # 1235551234.to_fs(:phone, country_code: 1, extension: 1343, delimiter: '.')
26
30
  # # => "+1.123.555.1234 x 1343"
27
31
  #
28
32
  # 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)')
33
+ # 1234567890.50.to_fs(:currency) # => "$1,234,567,890.50"
34
+ # 1234567890.506.to_fs(:currency) # => "$1,234,567,890.51"
35
+ # 1234567890.506.to_fs(:currency, precision: 3) # => "$1,234,567,890.506"
36
+ # 1234567890.506.to_fs(:currency, round_mode: :down) # => "$1,234,567,890.50"
37
+ # 1234567890.506.to_fs(:currency, locale: :fr) # => "1 234 567 890,51 €"
38
+ # -1234567890.50.to_fs(:currency, negative_format: '(%u%n)')
35
39
  # # => "($1,234,567,890.50)"
36
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
40
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '')
37
41
  # # => "&pound;1234567890,50"
38
- # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
42
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
39
43
  # # => "1234567890,50 &pound;"
40
44
  #
41
45
  # 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 %"
46
+ # 100.to_fs(:percentage) # => "100.000%"
47
+ # 100.to_fs(:percentage, precision: 0) # => "100%"
48
+ # 1000.to_fs(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
49
+ # 302.24398923423.to_fs(:percentage, precision: 5) # => "302.24399%"
50
+ # 302.24398923423.to_fs(:percentage, round_mode: :down) # => "302.243%"
51
+ # 1000.to_fs(:percentage, locale: :fr) # => "1 000,000%"
52
+ # 100.to_fs(:percentage, format: '%n %') # => "100.000 %"
49
53
  #
50
54
  # 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: ',')
55
+ # 12345678.to_fs(:delimited) # => "12,345,678"
56
+ # 12345678.05.to_fs(:delimited) # => "12,345,678.05"
57
+ # 12345678.to_fs(:delimited, delimiter: '.') # => "12.345.678"
58
+ # 12345678.to_fs(:delimited, delimiter: ',') # => "12,345,678"
59
+ # 12345678.05.to_fs(:delimited, separator: ' ') # => "12,345,678 05"
60
+ # 12345678.05.to_fs(:delimited, locale: :fr) # => "12 345 678,05"
61
+ # 98765432.98.to_fs(:delimited, delimiter: ' ', separator: ',')
58
62
  # # => "98 765 432,98"
59
63
  #
60
64
  # 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)
65
+ # 111.2345.to_fs(:rounded) # => "111.235"
66
+ # 111.2345.to_fs(:rounded, precision: 2) # => "111.23"
67
+ # 111.2345.to_fs(:rounded, precision: 2, round_mode: :up) # => "111.24"
68
+ # 13.to_fs(:rounded, precision: 5) # => "13.00000"
69
+ # 389.32314.to_fs(:rounded, precision: 0) # => "389"
70
+ # 111.2345.to_fs(:rounded, significant: true) # => "111"
71
+ # 111.2345.to_fs(:rounded, precision: 1, significant: true) # => "100"
72
+ # 13.to_fs(:rounded, precision: 5, significant: true) # => "13.000"
73
+ # 111.234.to_fs(:rounded, locale: :fr) # => "111,234"
74
+ # 13.to_fs(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
71
75
  # # => "13"
72
- # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
73
- # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
76
+ # 389.32314.to_fs(:rounded, precision: 4, significant: true) # => "389.3"
77
+ # 1111.2345.to_fs(:rounded, precision: 2, separator: ',', delimiter: '.')
74
78
  # # => "1.111,23"
75
79
  #
76
80
  # 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"
81
+ # 123.to_fs(:human_size) # => "123 Bytes"
82
+ # 1234.to_fs(:human_size) # => "1.21 KB"
83
+ # 12345.to_fs(:human_size) # => "12.1 KB"
84
+ # 1234567.to_fs(:human_size) # => "1.18 MB"
85
+ # 1234567890.to_fs(:human_size) # => "1.15 GB"
86
+ # 1234567890123.to_fs(:human_size) # => "1.12 TB"
87
+ # 1234567890123456.to_fs(:human_size) # => "1.1 PB"
88
+ # 1234567890123456789.to_fs(:human_size) # => "1.07 EB"
89
+ # 1234567.to_fs(:human_size, precision: 2) # => "1.2 MB"
90
+ # 1234567.to_fs(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
91
+ # 483989.to_fs(:human_size, precision: 2) # => "470 KB"
92
+ # 1234567.to_fs(:human_size, precision: 2, separator: ',') # => "1,2 MB"
93
+ # 1234567890123.to_fs(:human_size, precision: 5) # => "1.1228 TB"
94
+ # 524288000.to_fs(:human_size, precision: 5) # => "500 MB"
91
95
  #
92
96
  # 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,
97
+ # 123.to_fs(:human) # => "123"
98
+ # 1234.to_fs(:human) # => "1.23 Thousand"
99
+ # 12345.to_fs(:human) # => "12.3 Thousand"
100
+ # 1234567.to_fs(:human) # => "1.23 Million"
101
+ # 1234567890.to_fs(:human) # => "1.23 Billion"
102
+ # 1234567890123.to_fs(:human) # => "1.23 Trillion"
103
+ # 1234567890123456.to_fs(:human) # => "1.23 Quadrillion"
104
+ # 1234567890123456789.to_fs(:human) # => "1230 Quadrillion"
105
+ # 489939.to_fs(:human, precision: 2) # => "490 Thousand"
106
+ # 489939.to_fs(:human, precision: 2, round_mode: :down) # => "480 Thousand"
107
+ # 489939.to_fs(:human, precision: 4) # => "489.9 Thousand"
108
+ # 1234567.to_fs(:human, precision: 4,
109
+ # significant: false) # => "1.2346 Million"
110
+ # 1234567.to_fs(:human, precision: 1,
107
111
  # separator: ',',
108
- # significant: false) # => "1,2 Million"
109
- def to_s(format = nil, options = nil)
112
+ # significant: false) # => "1,2 Million"
113
+ def to_fs(format = nil, options = nil)
114
+ return to_s if format.nil?
115
+
110
116
  case format
111
- when nil
112
- super()
113
117
  when Integer, String
114
- super(format)
118
+ to_s(format)
115
119
  when :phone
116
120
  ActiveSupport::NumberHelper.number_to_phone(self, options || {})
117
121
  when :currency
@@ -127,11 +131,12 @@ module ActiveSupport
127
131
  when :human_size
128
132
  ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
129
133
  when Symbol
130
- super()
134
+ to_s
131
135
  else
132
- super(format)
136
+ to_s(format)
133
137
  end
134
138
  end
139
+ alias_method :to_formatted_s, :to_fs
135
140
  end
136
141
  end
137
142
 
@@ -1,11 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Object
4
- # A duck-type assistant method. For example, Active Support extends Date
5
- # to define an <tt>acts_like_date?</tt> method, and extends Time to define
6
- # <tt>acts_like_time?</tt>. As a result, we can do <tt>x.acts_like?(:time)</tt> and
7
- # <tt>x.acts_like?(:date)</tt> to do duck-type-safe comparisons, since classes that
8
- # we want to act like Time simply need to define an <tt>acts_like_time?</tt> method.
4
+ # Provides a way to check whether some class acts like some other class based on the existence of
5
+ # an appropriately-named marker method.
6
+ #
7
+ # A class that provides the same interface as <tt>SomeClass</tt> may define a marker method named
8
+ # <tt>acts_like_some_class?</tt> to signal its compatibility to callers of
9
+ # <tt>acts_like?(:some_class)</tt>.
10
+ #
11
+ # For example, Active Support extends <tt>Date</tt> to define an <tt>acts_like_date?</tt> method,
12
+ # and extends <tt>Time</tt> to define <tt>acts_like_time?</tt>. As a result, developers can call
13
+ # <tt>x.acts_like?(:time)</tt> and <tt>x.acts_like?(:date)</tt> to test duck-type compatibility,
14
+ # and classes that are able to act like <tt>Time</tt> can also define an <tt>acts_like_time?</tt>
15
+ # method to interoperate.
16
+ #
17
+ # Note that the marker method is only expected to exist. It isn't called, so its body or return
18
+ # value are irrelevant.
19
+ #
20
+ # ==== Example: A class that provides the same interface as <tt>String</tt>
21
+ #
22
+ # This class may define:
23
+ #
24
+ # class Stringish
25
+ # def acts_like_string?
26
+ # end
27
+ # end
28
+ #
29
+ # Then client code can query for duck-type-safeness this way:
30
+ #
31
+ # Stringish.new.acts_like?(:string) # => true
32
+ #
9
33
  def acts_like?(duck)
10
34
  case duck
11
35
  when :time
@@ -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)
@@ -53,3 +53,19 @@ class Hash
53
53
  hash
54
54
  end
55
55
  end
56
+
57
+ class Module
58
+ # Returns a copy of module or class if it's anonymous. If it's
59
+ # named, returns +self+.
60
+ #
61
+ # Object.deep_dup == Object # => true
62
+ # klass = Class.new
63
+ # klass.deep_dup == klass # => false
64
+ def deep_dup
65
+ if name.nil?
66
+ super
67
+ else
68
+ self
69
+ end
70
+ end
71
+ end
@@ -31,8 +31,8 @@ end
31
31
  class Method
32
32
  # Methods are not duplicable:
33
33
  #
34
- # method(:puts).duplicable? # => false
35
- # method(:puts).dup # => TypeError: allocator undefined for Method
34
+ # method(:puts).duplicable? # => false
35
+ # method(:puts).dup # => TypeError: allocator undefined for Method
36
36
  def duplicable?
37
37
  false
38
38
  end
@@ -41,8 +41,19 @@ end
41
41
  class UnboundMethod
42
42
  # Unbound methods are not duplicable:
43
43
  #
44
- # method(:puts).unbind.duplicable? # => false
45
- # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
44
+ # method(:puts).unbind.duplicable? # => false
45
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
46
+ def duplicable?
47
+ false
48
+ end
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
46
57
  def duplicable?
47
58
  false
48
59
  end
@@ -1,16 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Object
4
- # Returns true if this object is included in the argument. Argument must be
5
- # any object which responds to +#include?+. Usage:
4
+ # Returns true if this object is included in the argument.
5
+ #
6
+ # When argument is a +Range+, +#cover?+ is used to properly handle inclusion
7
+ # check within open ranges. Otherwise, argument must be any object which responds
8
+ # to +#include?+. Usage:
6
9
  #
7
10
  # characters = ["Konata", "Kagami", "Tsukasa"]
8
11
  # "Konata".in?(characters) # => true
9
12
  #
10
- # This will throw an +ArgumentError+ if the argument doesn't respond
11
- # to +#include?+.
13
+ # For non +Range+ arguments, this will throw an +ArgumentError+ if the argument
14
+ # doesn't respond to +#include?+.
12
15
  def in?(another_object)
13
- another_object.include?(self)
16
+ case another_object
17
+ when Range
18
+ another_object.cover?(self)
19
+ else
20
+ another_object.include?(self)
21
+ end
14
22
  rescue NoMethodError
15
23
  raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
16
24
  end
@@ -12,19 +12,29 @@ class Object
12
12
  #
13
13
  # C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
14
14
  def instance_values
15
- Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
15
+ instance_variables.to_h do |ivar|
16
+ [ivar[1..-1].freeze, instance_variable_get(ivar)]
17
+ end
16
18
  end
17
19
 
18
- # Returns an array of instance variable names as strings including "@".
19
- #
20
- # class C
21
- # def initialize(x, y)
22
- # @x, @y = x, y
23
- # end
24
- # end
25
- #
26
- # C.new(0, 1).instance_variable_names # => ["@y", "@x"]
27
- def instance_variable_names
28
- instance_variables.map(&:to_s)
20
+ if Symbol.method_defined?(:name) # RUBY_VERSION >= "3.0"
21
+ # Returns an array of instance variable names as strings including "@".
22
+ #
23
+ # class C
24
+ # def initialize(x, y)
25
+ # @x, @y = x, y
26
+ # end
27
+ # end
28
+ #
29
+ # C.new(0, 1).instance_variable_names # => ["@y", "@x"]
30
+ def instance_variable_names
31
+ instance_variables.map(&:name)
32
+ end
33
+ else
34
+ def instance_variable_names
35
+ variables = instance_variables
36
+ variables.map! { |s| s.to_s.freeze }
37
+ variables
38
+ end
29
39
  end
30
40
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Hack to load json gem first so we can overwrite its to_json.
3
+ # Hack to load JSON gem first so we can override its to_json.
4
4
  require "json"
5
5
  require "bigdecimal"
6
6
  require "ipaddr"
@@ -19,8 +19,7 @@ require "active_support/core_ext/date/conversions"
19
19
  # The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
20
20
  # their default behavior. That said, we need to define the basic to_json method in all of them,
21
21
  # otherwise they will always use to_json gem implementation, which is backwards incompatible in
22
- # several cases (for instance, the JSON implementation for Hash does not work) with inheritance
23
- # 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.
24
23
  #
25
24
  # On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
26
25
  # JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
@@ -30,7 +29,7 @@ require "active_support/core_ext/date/conversions"
30
29
  # It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
31
30
  # bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
32
31
  # ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
33
- # should give exactly the same results with or without active support.
32
+ # should give exactly the same results with or without Active Support.
34
33
 
35
34
  module ActiveSupport
36
35
  module ToJsonWithActiveSupportEncoder # :nodoc:
@@ -50,8 +49,14 @@ end
50
49
  klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
51
50
  end
52
51
 
52
+ class Module
53
+ def as_json(options = nil) # :nodoc:
54
+ name
55
+ end
56
+ end
57
+
53
58
  class Object
54
- def as_json(options = nil) #:nodoc:
59
+ def as_json(options = nil) # :nodoc:
55
60
  if respond_to?(:to_hash)
56
61
  to_hash.as_json(options)
57
62
  else
@@ -60,44 +65,52 @@ class Object
60
65
  end
61
66
  end
62
67
 
63
- class Struct #:nodoc:
68
+ if RUBY_VERSION >= "3.2"
69
+ class Data # :nodoc:
70
+ def as_json(options = nil)
71
+ to_h.as_json(options)
72
+ end
73
+ end
74
+ end
75
+
76
+ class Struct # :nodoc:
64
77
  def as_json(options = nil)
65
- Hash[members.zip(values)].as_json(options)
78
+ to_h.as_json(options)
66
79
  end
67
80
  end
68
81
 
69
82
  class TrueClass
70
- def as_json(options = nil) #:nodoc:
83
+ def as_json(options = nil) # :nodoc:
71
84
  self
72
85
  end
73
86
  end
74
87
 
75
88
  class FalseClass
76
- def as_json(options = nil) #:nodoc:
89
+ def as_json(options = nil) # :nodoc:
77
90
  self
78
91
  end
79
92
  end
80
93
 
81
94
  class NilClass
82
- def as_json(options = nil) #:nodoc:
95
+ def as_json(options = nil) # :nodoc:
83
96
  self
84
97
  end
85
98
  end
86
99
 
87
100
  class String
88
- def as_json(options = nil) #:nodoc:
101
+ def as_json(options = nil) # :nodoc:
89
102
  self
90
103
  end
91
104
  end
92
105
 
93
106
  class Symbol
94
- def as_json(options = nil) #:nodoc:
107
+ def as_json(options = nil) # :nodoc:
95
108
  to_s
96
109
  end
97
110
  end
98
111
 
99
112
  class Numeric
100
- def as_json(options = nil) #:nodoc:
113
+ def as_json(options = nil) # :nodoc:
101
114
  self
102
115
  end
103
116
  end
@@ -105,7 +118,7 @@ end
105
118
  class Float
106
119
  # Encoding Infinity or NaN to JSON should return "null". The default returns
107
120
  # "Infinity" or "NaN" which are not valid JSON.
108
- def as_json(options = nil) #:nodoc:
121
+ def as_json(options = nil) # :nodoc:
109
122
  finite? ? self : nil
110
123
  end
111
124
  end
@@ -120,43 +133,43 @@ class BigDecimal
120
133
  # if the other end knows by contract that the data is supposed to be a
121
134
  # BigDecimal, it still has the chance to post-process the string and get the
122
135
  # real value.
123
- def as_json(options = nil) #:nodoc:
136
+ def as_json(options = nil) # :nodoc:
124
137
  finite? ? to_s : nil
125
138
  end
126
139
  end
127
140
 
128
141
  class Regexp
129
- def as_json(options = nil) #:nodoc:
142
+ def as_json(options = nil) # :nodoc:
130
143
  to_s
131
144
  end
132
145
  end
133
146
 
134
147
  module Enumerable
135
- def as_json(options = nil) #:nodoc:
148
+ def as_json(options = nil) # :nodoc:
136
149
  to_a.as_json(options)
137
150
  end
138
151
  end
139
152
 
140
153
  class IO
141
- def as_json(options = nil) #:nodoc:
154
+ def as_json(options = nil) # :nodoc:
142
155
  to_s
143
156
  end
144
157
  end
145
158
 
146
159
  class Range
147
- def as_json(options = nil) #:nodoc:
160
+ def as_json(options = nil) # :nodoc:
148
161
  to_s
149
162
  end
150
163
  end
151
164
 
152
165
  class Array
153
- def as_json(options = nil) #:nodoc:
166
+ def as_json(options = nil) # :nodoc:
154
167
  map { |v| options ? v.as_json(options.dup) : v.as_json }
155
168
  end
156
169
  end
157
170
 
158
171
  class Hash
159
- def as_json(options = nil) #:nodoc:
172
+ def as_json(options = nil) # :nodoc:
160
173
  # create a subset of the hash by applying :only or :except
161
174
  subset = if options
162
175
  if attrs = options[:only]
@@ -179,7 +192,7 @@ class Hash
179
192
  end
180
193
 
181
194
  class Time
182
- def as_json(options = nil) #:nodoc:
195
+ def as_json(options = nil) # :nodoc:
183
196
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
184
197
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
185
198
  else
@@ -189,7 +202,7 @@ class Time
189
202
  end
190
203
 
191
204
  class Date
192
- def as_json(options = nil) #:nodoc:
205
+ def as_json(options = nil) # :nodoc:
193
206
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
194
207
  strftime("%Y-%m-%d")
195
208
  else
@@ -199,7 +212,7 @@ class Date
199
212
  end
200
213
 
201
214
  class DateTime
202
- def as_json(options = nil) #:nodoc:
215
+ def as_json(options = nil) # :nodoc:
203
216
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
204
217
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
205
218
  else
@@ -208,13 +221,13 @@ class DateTime
208
221
  end
209
222
  end
210
223
 
211
- class URI::Generic #:nodoc:
224
+ class URI::Generic # :nodoc:
212
225
  def as_json(options = nil)
213
226
  to_s
214
227
  end
215
228
  end
216
229
 
217
- class Pathname #:nodoc:
230
+ class Pathname # :nodoc:
218
231
  def as_json(options = nil)
219
232
  to_s
220
233
  end
@@ -226,7 +239,7 @@ class IPAddr # :nodoc:
226
239
  end
227
240
  end
228
241
 
229
- class Process::Status #:nodoc:
242
+ class Process::Status # :nodoc:
230
243
  def as_json(options = nil)
231
244
  { exitstatus: exitstatus, pid: pid }
232
245
  end
@@ -72,14 +72,12 @@ class Hash
72
72
  #
73
73
  # The string pairs "key=value" that conform the query string
74
74
  # are sorted lexicographically in ascending order.
75
- #
76
- # This method is also aliased as +to_param+.
77
75
  def to_query(namespace = nil)
78
- query = collect do |key, value|
76
+ query = filter_map do |key, value|
79
77
  unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
80
78
  value.to_query(namespace ? "#{namespace}[#{key}]" : key)
81
79
  end
82
- end.compact
80
+ end
83
81
 
84
82
  query.sort! unless namespace.to_s.include?("[]")
85
83
  query.join("&")