activesupport 7.0.0 → 7.2.2.1

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +156 -255
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +3 -1
  6. data/lib/active_support/array_inquirer.rb +3 -1
  7. data/lib/active_support/backtrace_cleaner.rb +41 -9
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/broadcast_logger.rb +251 -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 +49 -17
  14. data/lib/active_support/cache/mem_cache_store.rb +111 -129
  15. data/lib/active_support/cache/memory_store.rb +81 -26
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +175 -154
  18. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +31 -13
  20. data/lib/active_support/cache.rb +457 -377
  21. data/lib/active_support/callbacks.rb +123 -139
  22. data/lib/active_support/code_generator.rb +15 -10
  23. data/lib/active_support/concern.rb +4 -2
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/configurable.rb +12 -2
  27. data/lib/active_support/core_ext/array/conversions.rb +7 -9
  28. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  29. data/lib/active_support/core_ext/array.rb +0 -1
  30. data/lib/active_support/core_ext/class/subclasses.rb +4 -15
  31. data/lib/active_support/core_ext/date/blank.rb +4 -0
  32. data/lib/active_support/core_ext/date/calculations.rb +20 -5
  33. data/lib/active_support/core_ext/date/conversions.rb +15 -16
  34. data/lib/active_support/core_ext/date.rb +0 -1
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
  36. data/lib/active_support/core_ext/date_and_time/compatibility.rb +29 -2
  37. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  38. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  39. data/lib/active_support/core_ext/date_time/conversions.rb +15 -15
  40. data/lib/active_support/core_ext/date_time.rb +0 -1
  41. data/lib/active_support/core_ext/digest/uuid.rb +7 -10
  42. data/lib/active_support/core_ext/enumerable.rb +51 -101
  43. data/lib/active_support/core_ext/erb/util.rb +201 -0
  44. data/lib/active_support/core_ext/file/atomic.rb +2 -0
  45. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  46. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  49. data/lib/active_support/core_ext/hash/keys.rb +7 -7
  50. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  51. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  52. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  53. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  54. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +38 -20
  55. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  56. data/lib/active_support/core_ext/module/delegation.rb +20 -119
  57. data/lib/active_support/core_ext/module/deprecation.rb +12 -12
  58. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  59. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  60. data/lib/active_support/core_ext/numeric/conversions.rb +77 -75
  61. data/lib/active_support/core_ext/numeric.rb +0 -1
  62. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  63. data/lib/active_support/core_ext/object/blank.rb +45 -1
  64. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  65. data/lib/active_support/core_ext/object/duplicable.rb +25 -16
  66. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  67. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  68. data/lib/active_support/core_ext/object/json.rb +17 -7
  69. data/lib/active_support/core_ext/object/to_query.rb +0 -2
  70. data/lib/active_support/core_ext/object/with.rb +46 -0
  71. data/lib/active_support/core_ext/object/with_options.rb +9 -9
  72. data/lib/active_support/core_ext/object.rb +1 -0
  73. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  74. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  75. data/lib/active_support/core_ext/pathname.rb +1 -0
  76. data/lib/active_support/core_ext/range/conversions.rb +32 -11
  77. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  78. data/lib/active_support/core_ext/range.rb +1 -2
  79. data/lib/active_support/core_ext/securerandom.rb +2 -6
  80. data/lib/active_support/core_ext/string/conversions.rb +3 -3
  81. data/lib/active_support/core_ext/string/filters.rb +21 -15
  82. data/lib/active_support/core_ext/string/indent.rb +1 -1
  83. data/lib/active_support/core_ext/string/inflections.rb +16 -9
  84. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  85. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  86. data/lib/active_support/core_ext/string/output_safety.rb +39 -150
  87. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  88. data/lib/active_support/core_ext/time/calculations.rb +42 -32
  89. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  90. data/lib/active_support/core_ext/time/conversions.rb +13 -15
  91. data/lib/active_support/core_ext/time/zones.rb +8 -9
  92. data/lib/active_support/core_ext/time.rb +0 -1
  93. data/lib/active_support/core_ext.rb +0 -1
  94. data/lib/active_support/current_attributes.rb +53 -46
  95. data/lib/active_support/deep_mergeable.rb +53 -0
  96. data/lib/active_support/delegation.rb +202 -0
  97. data/lib/active_support/dependencies/autoload.rb +9 -16
  98. data/lib/active_support/deprecation/behaviors.rb +65 -42
  99. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  100. data/lib/active_support/deprecation/deprecators.rb +104 -0
  101. data/lib/active_support/deprecation/disallowed.rb +6 -8
  102. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  103. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  104. data/lib/active_support/deprecation/reporting.rb +49 -27
  105. data/lib/active_support/deprecation.rb +39 -9
  106. data/lib/active_support/deprecator.rb +7 -0
  107. data/lib/active_support/descendants_tracker.rb +66 -175
  108. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  109. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  110. data/lib/active_support/duration.rb +13 -7
  111. data/lib/active_support/encrypted_configuration.rb +63 -10
  112. data/lib/active_support/encrypted_file.rb +29 -13
  113. data/lib/active_support/environment_inquirer.rb +22 -2
  114. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  115. data/lib/active_support/error_reporter.rb +160 -36
  116. data/lib/active_support/evented_file_update_checker.rb +19 -7
  117. data/lib/active_support/execution_wrapper.rb +23 -28
  118. data/lib/active_support/file_update_checker.rb +5 -3
  119. data/lib/active_support/fork_tracker.rb +4 -32
  120. data/lib/active_support/gem_version.rb +4 -4
  121. data/lib/active_support/gzip.rb +2 -0
  122. data/lib/active_support/hash_with_indifferent_access.rb +41 -25
  123. data/lib/active_support/html_safe_translation.rb +19 -6
  124. data/lib/active_support/i18n.rb +1 -1
  125. data/lib/active_support/i18n_railtie.rb +20 -13
  126. data/lib/active_support/inflector/inflections.rb +2 -0
  127. data/lib/active_support/inflector/methods.rb +28 -18
  128. data/lib/active_support/inflector/transliterate.rb +4 -2
  129. data/lib/active_support/isolated_execution_state.rb +39 -19
  130. data/lib/active_support/json/decoding.rb +2 -1
  131. data/lib/active_support/json/encoding.rb +25 -43
  132. data/lib/active_support/key_generator.rb +13 -5
  133. data/lib/active_support/lazy_load_hooks.rb +33 -7
  134. data/lib/active_support/locale/en.yml +2 -0
  135. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  136. data/lib/active_support/log_subscriber.rb +76 -36
  137. data/lib/active_support/logger.rb +22 -60
  138. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  139. data/lib/active_support/message_encryptor.rb +200 -55
  140. data/lib/active_support/message_encryptors.rb +141 -0
  141. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  142. data/lib/active_support/message_pack/extensions.rb +305 -0
  143. data/lib/active_support/message_pack/serializer.rb +63 -0
  144. data/lib/active_support/message_pack.rb +50 -0
  145. data/lib/active_support/message_verifier.rb +220 -89
  146. data/lib/active_support/message_verifiers.rb +135 -0
  147. data/lib/active_support/messages/codec.rb +65 -0
  148. data/lib/active_support/messages/metadata.rb +111 -45
  149. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  150. data/lib/active_support/messages/rotator.rb +34 -32
  151. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  152. data/lib/active_support/multibyte/chars.rb +4 -2
  153. data/lib/active_support/multibyte/unicode.rb +9 -37
  154. data/lib/active_support/notifications/fanout.rb +248 -87
  155. data/lib/active_support/notifications/instrumenter.rb +93 -25
  156. data/lib/active_support/notifications.rb +38 -31
  157. data/lib/active_support/number_helper/number_converter.rb +16 -7
  158. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  159. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  160. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  161. data/lib/active_support/number_helper.rb +379 -317
  162. data/lib/active_support/option_merger.rb +4 -4
  163. data/lib/active_support/ordered_hash.rb +3 -3
  164. data/lib/active_support/ordered_options.rb +68 -16
  165. data/lib/active_support/parameter_filter.rb +103 -84
  166. data/lib/active_support/proxy_object.rb +8 -3
  167. data/lib/active_support/railtie.rb +30 -25
  168. data/lib/active_support/reloader.rb +13 -5
  169. data/lib/active_support/rescuable.rb +12 -10
  170. data/lib/active_support/secure_compare_rotator.rb +17 -10
  171. data/lib/active_support/string_inquirer.rb +4 -2
  172. data/lib/active_support/subscriber.rb +10 -27
  173. data/lib/active_support/syntax_error_proxy.rb +60 -0
  174. data/lib/active_support/tagged_logging.rb +64 -25
  175. data/lib/active_support/test_case.rb +160 -7
  176. data/lib/active_support/testing/assertions.rb +29 -13
  177. data/lib/active_support/testing/autorun.rb +0 -2
  178. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  179. data/lib/active_support/testing/deprecation.rb +20 -27
  180. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  181. data/lib/active_support/testing/isolation.rb +46 -33
  182. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  183. data/lib/active_support/testing/parallelization/server.rb +3 -0
  184. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  185. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  186. data/lib/active_support/testing/stream.rb +1 -1
  187. data/lib/active_support/testing/strict_warnings.rb +43 -0
  188. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  189. data/lib/active_support/testing/time_helpers.rb +38 -16
  190. data/lib/active_support/time_with_zone.rb +28 -54
  191. data/lib/active_support/values/time_zone.rb +26 -15
  192. data/lib/active_support/version.rb +1 -1
  193. data/lib/active_support/xml_mini/jdom.rb +3 -10
  194. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  195. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  196. data/lib/active_support/xml_mini/rexml.rb +1 -1
  197. data/lib/active_support/xml_mini.rb +13 -4
  198. data/lib/active_support.rb +15 -3
  199. metadata +142 -21
  200. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  201. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
  202. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
  203. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  204. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
  205. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
  206. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  207. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
  208. data/lib/active_support/core_ext/uri.rb +0 -5
  209. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  210. data/lib/active_support/per_thread_registry.rb +0 -65
  211. data/lib/active_support/ruby_features.rb +0 -7
@@ -5,11 +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.
11
13
  #
12
- # This method is aliased to <tt>to_fs</tt>.
14
+ # This method is aliased to <tt>to_formatted_s</tt>.
13
15
  #
14
16
  # ==== Options
15
17
  #
@@ -18,97 +20,97 @@ module ActiveSupport
18
20
  # ==== Examples
19
21
  #
20
22
  # Phone Numbers:
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: '.')
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: '.')
28
30
  # # => "+1.123.555.1234 x 1343"
29
31
  #
30
32
  # Currency:
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)')
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)')
37
39
  # # => "($1,234,567,890.50)"
38
- # 1234567890.50.to_formatted_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
40
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '')
39
41
  # # => "&pound;1234567890,50"
40
- # 1234567890.50.to_formatted_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
42
+ # 1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
41
43
  # # => "1234567890,50 &pound;"
42
44
  #
43
45
  # Percentage:
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 %"
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 %"
51
53
  #
52
54
  # Delimited:
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: ',')
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: ',')
60
62
  # # => "98 765 432,98"
61
63
  #
62
64
  # Rounded:
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)
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)
73
75
  # # => "13"
74
- # 389.32314.to_formatted_s(:rounded, precision: 4, significant: true) # => "389.3"
75
- # 1111.2345.to_formatted_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: '.')
76
78
  # # => "1.111,23"
77
79
  #
78
80
  # Human-friendly size in Bytes:
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"
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"
93
95
  #
94
96
  # Human-friendly format:
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,
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,
107
109
  # significant: false) # => "1.2346 Million"
108
- # 1234567.to_formatted_s(:human, precision: 1,
110
+ # 1234567.to_fs(:human, precision: 1,
109
111
  # separator: ',',
110
112
  # significant: false) # => "1,2 Million"
111
- def to_formatted_s(format = nil, options = nil)
113
+ def to_fs(format = nil, options = nil)
112
114
  return to_s if format.nil?
113
115
 
114
116
  case format
@@ -134,10 +136,10 @@ module ActiveSupport
134
136
  to_s(format)
135
137
  end
136
138
  end
137
- alias_method :to_fs, :to_formatted_s
139
+ alias_method :to_formatted_s, :to_fs
138
140
  end
139
141
  end
140
142
 
141
- Integer.prepend ActiveSupport::NumericWithFormat
142
- Float.prepend ActiveSupport::NumericWithFormat
143
- BigDecimal.prepend ActiveSupport::NumericWithFormat
143
+ Integer.include ActiveSupport::NumericWithFormat
144
+ Float.include ActiveSupport::NumericWithFormat
145
+ BigDecimal.include ActiveSupport::NumericWithFormat
@@ -3,4 +3,3 @@
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"]
@@ -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
@@ -16,7 +16,7 @@ class Object
16
16
  #
17
17
  # @return [true, false]
18
18
  def blank?
19
- respond_to?(:empty?) ? !!empty? : !self
19
+ respond_to?(:empty?) ? !!empty? : false
20
20
  end
21
21
 
22
22
  # An object is present if it's not blank.
@@ -56,6 +56,10 @@ class NilClass
56
56
  def blank?
57
57
  true
58
58
  end
59
+
60
+ def present? # :nodoc:
61
+ false
62
+ end
59
63
  end
60
64
 
61
65
  class FalseClass
@@ -67,6 +71,10 @@ class FalseClass
67
71
  def blank?
68
72
  true
69
73
  end
74
+
75
+ def present? # :nodoc:
76
+ false
77
+ end
70
78
  end
71
79
 
72
80
  class TrueClass
@@ -78,6 +86,10 @@ class TrueClass
78
86
  def blank?
79
87
  false
80
88
  end
89
+
90
+ def present? # :nodoc:
91
+ true
92
+ end
81
93
  end
82
94
 
83
95
  class Array
@@ -88,6 +100,10 @@ class Array
88
100
  #
89
101
  # @return [true, false]
90
102
  alias_method :blank?, :empty?
103
+
104
+ def present? # :nodoc:
105
+ !empty?
106
+ end
91
107
  end
92
108
 
93
109
  class Hash
@@ -98,6 +114,22 @@ class Hash
98
114
  #
99
115
  # @return [true, false]
100
116
  alias_method :blank?, :empty?
117
+
118
+ def present? # :nodoc:
119
+ !empty?
120
+ end
121
+ end
122
+
123
+ class Symbol
124
+ # A Symbol is blank if it's empty:
125
+ #
126
+ # :''.blank? # => true
127
+ # :symbol.blank? # => false
128
+ alias_method :blank?, :empty?
129
+
130
+ def present? # :nodoc:
131
+ !empty?
132
+ end
101
133
  end
102
134
 
103
135
  class String
@@ -129,6 +161,10 @@ class String
129
161
  ENCODED_BLANKS[self.encoding].match?(self)
130
162
  end
131
163
  end
164
+
165
+ def present? # :nodoc:
166
+ !blank?
167
+ end
132
168
  end
133
169
 
134
170
  class Numeric # :nodoc:
@@ -141,6 +177,10 @@ class Numeric # :nodoc:
141
177
  def blank?
142
178
  false
143
179
  end
180
+
181
+ def present?
182
+ true
183
+ end
144
184
  end
145
185
 
146
186
  class Time # :nodoc:
@@ -152,4 +192,8 @@ class Time # :nodoc:
152
192
  def blank?
153
193
  false
154
194
  end
195
+
196
+ def present?
197
+ true
198
+ end
155
199
  end
@@ -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
@@ -28,23 +28,32 @@ class Object
28
28
  end
29
29
  end
30
30
 
31
- class Method
32
- # Methods are not duplicable:
33
- #
34
- # method(:puts).duplicable? # => false
35
- # method(:puts).dup # => TypeError: allocator undefined for Method
36
- def duplicable?
37
- false
38
- end
31
+ methods_are_duplicable = begin
32
+ Object.instance_method(:duplicable?).dup
33
+ true
34
+ rescue TypeError
35
+ false
39
36
  end
40
37
 
41
- class UnboundMethod
42
- # Unbound methods are not duplicable:
43
- #
44
- # method(:puts).unbind.duplicable? # => false
45
- # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
46
- def duplicable?
47
- false
38
+ unless methods_are_duplicable
39
+ class Method
40
+ # Methods are not duplicable:
41
+ #
42
+ # method(:puts).duplicable? # => false
43
+ # method(:puts).dup # => TypeError: allocator undefined for Method
44
+ def duplicable?
45
+ false
46
+ end
47
+ end
48
+
49
+ class UnboundMethod
50
+ # Unbound methods are not duplicable:
51
+ #
52
+ # method(:puts).unbind.duplicable? # => false
53
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
54
+ def duplicable?
55
+ false
56
+ end
48
57
  end
49
58
  end
50
59
 
@@ -53,7 +62,7 @@ require "singleton"
53
62
  module Singleton
54
63
  # Singleton instances are not duplicable:
55
64
  #
56
- # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
65
+ # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
57
66
  def duplicable?
58
67
  false
59
68
  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,7 +12,9 @@ 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
20
  # Returns an array of instance variable names as strings including "@".
@@ -25,6 +27,6 @@ class Object
25
27
  #
26
28
  # C.new(0, 1).instance_variable_names # => ["@y", "@x"]
27
29
  def instance_variable_names
28
- instance_variables.map(&:to_s)
30
+ instance_variables.map(&:name)
29
31
  end
30
32
  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"
@@ -29,7 +29,7 @@ require "active_support/core_ext/date/conversions"
29
29
  # It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
30
30
  # bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
31
31
  # ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
32
- # should give exactly the same results with or without active support.
32
+ # should give exactly the same results with or without Active Support.
33
33
 
34
34
  module ActiveSupport
35
35
  module ToJsonWithActiveSupportEncoder # :nodoc:
@@ -46,7 +46,7 @@ module ActiveSupport
46
46
  end
47
47
 
48
48
  [Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].reverse_each do |klass|
49
- klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
49
+ klass.include(ActiveSupport::ToJsonWithActiveSupportEncoder)
50
50
  end
51
51
 
52
52
  class Module
@@ -65,9 +65,17 @@ class Object
65
65
  end
66
66
  end
67
67
 
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
+
68
76
  class Struct # :nodoc:
69
77
  def as_json(options = nil)
70
- Hash[members.zip(values)].as_json(options)
78
+ to_h.as_json(options)
71
79
  end
72
80
  end
73
81
 
@@ -225,9 +233,11 @@ class Pathname # :nodoc:
225
233
  end
226
234
  end
227
235
 
228
- class IPAddr # :nodoc:
229
- def as_json(options = nil)
230
- to_s
236
+ unless IPAddr.method_defined?(:as_json, false)
237
+ class IPAddr # :nodoc:
238
+ def as_json(options = nil)
239
+ to_s
240
+ end
231
241
  end
232
242
  end
233
243
 
@@ -72,8 +72,6 @@ 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
76
  query = filter_map do |key, value|
79
77
  unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Object
4
+ # Set and restore public attributes around a block.
5
+ #
6
+ # client.timeout # => 5
7
+ # client.with(timeout: 1) do |c|
8
+ # c.timeout # => 1
9
+ # end
10
+ # client.timeout # => 5
11
+ #
12
+ # The receiver is yielded to the provided block.
13
+ #
14
+ # This method is a shorthand for the common begin/ensure pattern:
15
+ #
16
+ # old_value = object.attribute
17
+ # begin
18
+ # object.attribute = new_value
19
+ # # do things
20
+ # ensure
21
+ # object.attribute = old_value
22
+ # end
23
+ #
24
+ # It can be used on any object as long as both the reader and writer methods
25
+ # are public.
26
+ def with(**attributes)
27
+ old_values = {}
28
+ begin
29
+ attributes.each do |key, value|
30
+ old_values[key] = public_send(key)
31
+ public_send("#{key}=", value)
32
+ end
33
+ yield self
34
+ ensure
35
+ old_values.each do |key, old_value|
36
+ public_send("#{key}=", old_value)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ # #with isn't usable on immediates, so we might as well undefine the
43
+ # method in common immediate classes to avoid potential confusion.
44
+ [NilClass, TrueClass, FalseClass, Integer, Float, Symbol].each do |klass|
45
+ klass.undef_method(:with)
46
+ end
@@ -5,9 +5,9 @@ require "active_support/option_merger"
5
5
  class Object
6
6
  # An elegant way to factor duplication out of options passed to a series of
7
7
  # method calls. Each method called in the block, with the block variable as
8
- # the receiver, will have its options merged with the default +options+ hash
9
- # provided. Each method called on the block variable must take an options
10
- # hash as its final argument.
8
+ # the receiver, will have its options merged with the default +options+
9
+ # <tt>Hash</tt> or <tt>Hash</tt>-like object provided. Each method called on
10
+ # the block variable must take an options hash as its final argument.
11
11
  #
12
12
  # Without <tt>with_options</tt>, this code contains duplication:
13
13
  #
@@ -64,11 +64,11 @@ class Object
64
64
  #
65
65
  # Hence the inherited default for +if+ key is ignored.
66
66
  #
67
- # NOTE: You cannot call class methods implicitly inside of with_options.
67
+ # NOTE: You cannot call class methods implicitly inside of +with_options+.
68
68
  # You can access these methods using the class name instead:
69
69
  #
70
70
  # class Phone < ActiveRecord::Base
71
- # enum phone_number_type: { home: 0, office: 1, mobile: 2 }
71
+ # enum :phone_number_type, { home: 0, office: 1, mobile: 2 }
72
72
  #
73
73
  # with_options presence: true do
74
74
  # validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
@@ -83,11 +83,11 @@ class Object
83
83
  # end
84
84
  # end
85
85
  #
86
- # # styled.link_to "I'm red", "/"
87
- # # #=> <a href="/" style="color: red;">I'm red</a>
86
+ # styled.link_to "I'm red", "/"
87
+ # # => <a href="/" style="color: red;">I'm red</a>
88
88
  #
89
- # # styled.button_tag "I'm red too!"
90
- # # #=> <button style="color: red;">I'm red too!</button>
89
+ # styled.button_tag "I'm red too!"
90
+ # # => <button style="color: red;">I'm red too!</button>
91
91
  #
92
92
  def with_options(options, &block)
93
93
  option_merger = ActiveSupport::OptionMerger.new(self, options)
@@ -13,4 +13,5 @@ require "active_support/core_ext/object/instance_variables"
13
13
  require "active_support/core_ext/object/json"
14
14
  require "active_support/core_ext/object/to_param"
15
15
  require "active_support/core_ext/object/to_query"
16
+ require "active_support/core_ext/object/with"
16
17
  require "active_support/core_ext/object/with_options"