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
@@ -11,34 +11,50 @@ module ActiveSupport
11
11
  attr_accessor :gem_name
12
12
 
13
13
  # Outputs a deprecation warning to the output configured by
14
- # <tt>ActiveSupport::Deprecation.behavior</tt>.
14
+ # ActiveSupport::Deprecation#behavior.
15
15
  #
16
- # ActiveSupport::Deprecation.warn('something broke!')
16
+ # ActiveSupport::Deprecation.new.warn('something broke!')
17
17
  # # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
18
18
  def warn(message = nil, callstack = nil)
19
19
  return if silenced
20
20
 
21
21
  callstack ||= caller_locations(2)
22
- deprecation_message(callstack, message).tap do |m|
22
+ deprecation_message(callstack, message).tap do |full_message|
23
23
  if deprecation_disallowed?(message)
24
- disallowed_behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
24
+ disallowed_behavior.each { |b| b.call(full_message, callstack, self) }
25
25
  else
26
- behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
26
+ behavior.each { |b| b.call(full_message, callstack, self) }
27
27
  end
28
28
  end
29
29
  end
30
30
 
31
31
  # Silence deprecation warnings within the block.
32
32
  #
33
- # ActiveSupport::Deprecation.warn('something broke!')
33
+ # deprecator = ActiveSupport::Deprecation.new
34
+ # deprecator.warn('something broke!')
34
35
  # # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
35
36
  #
36
- # ActiveSupport::Deprecation.silence do
37
- # ActiveSupport::Deprecation.warn('something broke!')
37
+ # deprecator.silence do
38
+ # deprecator.warn('something broke!')
38
39
  # end
39
40
  # # => nil
40
41
  def silence(&block)
41
- @silenced_thread.bind(true, &block)
42
+ begin_silence
43
+ block.call
44
+ ensure
45
+ end_silence
46
+ end
47
+
48
+ def begin_silence # :nodoc:
49
+ @silence_counter.value += 1
50
+ end
51
+
52
+ def end_silence # :nodoc:
53
+ @silence_counter.value -= 1
54
+ end
55
+
56
+ def silenced
57
+ @silenced || @silence_counter.value.nonzero?
42
58
  end
43
59
 
44
60
  # Allow previously disallowed deprecation warnings within the block.
@@ -46,27 +62,28 @@ module ActiveSupport
46
62
  # expressions. (Symbols are treated as strings). These are compared against
47
63
  # the text of deprecation warning messages generated within the block.
48
64
  # Matching warnings will be exempt from the rules set by
49
- # +ActiveSupport::Deprecation.disallowed_warnings+
65
+ # ActiveSupport::Deprecation#disallowed_warnings.
50
66
  #
51
67
  # The optional <tt>if:</tt> argument accepts a truthy/falsy value or an object that
52
68
  # responds to <tt>.call</tt>. If truthy, then matching warnings will be allowed.
53
69
  # If falsey then the method yields to the block without allowing the warning.
54
70
  #
55
- # ActiveSupport::Deprecation.disallowed_behavior = :raise
56
- # ActiveSupport::Deprecation.disallowed_warnings = [
71
+ # deprecator = ActiveSupport::Deprecation.new
72
+ # deprecator.disallowed_behavior = :raise
73
+ # deprecator.disallowed_warnings = [
57
74
  # "something broke"
58
75
  # ]
59
76
  #
60
- # ActiveSupport::Deprecation.warn('something broke!')
77
+ # deprecator.warn('something broke!')
61
78
  # # => ActiveSupport::DeprecationException
62
79
  #
63
- # ActiveSupport::Deprecation.allow ['something broke'] do
64
- # ActiveSupport::Deprecation.warn('something broke!')
80
+ # deprecator.allow ['something broke'] do
81
+ # deprecator.warn('something broke!')
65
82
  # end
66
83
  # # => nil
67
84
  #
68
- # ActiveSupport::Deprecation.allow ['something broke'], if: Rails.env.production? do
69
- # ActiveSupport::Deprecation.warn('something broke!')
85
+ # deprecator.allow ['something broke'], if: Rails.env.production? do
86
+ # deprecator.warn('something broke!')
70
87
  # end
71
88
  # # => ActiveSupport::DeprecationException for dev/test, nil for production
72
89
  def allow(allowed_warnings = :all, if: true, &block)
@@ -79,10 +96,6 @@ module ActiveSupport
79
96
  end
80
97
  end
81
98
 
82
- def silenced
83
- @silenced || @silenced_thread.value
84
- end
85
-
86
99
  def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
87
100
  caller_backtrace ||= caller_locations(2)
88
101
  deprecated_method_warning(deprecated_method_name, message).tap do |msg|
@@ -125,18 +138,26 @@ module ActiveSupport
125
138
  end
126
139
 
127
140
  def extract_callstack(callstack)
141
+ return [] if callstack.empty?
128
142
  return _extract_callstack(callstack) if callstack.first.is_a? String
129
143
 
130
144
  offending_line = callstack.find { |frame|
131
- frame.absolute_path && !ignored_callstack(frame.absolute_path)
145
+ # Code generated with `eval` doesn't have an `absolute_path`, e.g. templates.
146
+ path = frame.absolute_path || frame.path
147
+ path && !ignored_callstack?(path)
132
148
  } || callstack.first
133
149
 
134
150
  [offending_line.path, offending_line.lineno, offending_line.label]
135
151
  end
136
152
 
137
153
  def _extract_callstack(callstack)
138
- warn "Please pass `caller_locations` to the deprecation API" if $VERBOSE
139
- offending_line = callstack.find { |line| !ignored_callstack(line) } || callstack.first
154
+ ActiveSupport.deprecator.warn(<<~MESSAGE)
155
+ Passing the result of `caller` to ActiveSupport::Deprecation#warn is deprecated and will be removed in Rails 8.0.
156
+
157
+ Please pass the result of `caller_locations` instead.
158
+ MESSAGE
159
+
160
+ offending_line = callstack.find { |line| !ignored_callstack?(line) } || callstack.first
140
161
 
141
162
  if offending_line
142
163
  if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
@@ -147,10 +168,11 @@ module ActiveSupport
147
168
  end
148
169
  end
149
170
 
150
- RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/"
171
+ RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/" # :nodoc:
172
+ LIB_DIR = RbConfig::CONFIG["libdir"] # :nodoc:
151
173
 
152
- def ignored_callstack(path)
153
- path.start_with?(RAILS_GEM_ROOT) || path.start_with?(RbConfig::CONFIG["rubylibdir"])
174
+ def ignored_callstack?(path)
175
+ path.start_with?(RAILS_GEM_ROOT, LIB_DIR) || path.include?("<internal:")
154
176
  end
155
177
  end
156
178
  end
@@ -1,10 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "singleton"
4
-
5
3
  module ActiveSupport
6
- # \Deprecation specifies the API used by Rails to deprecate methods, instance
7
- # variables, objects and constants.
4
+ # = Active Support \Deprecation
5
+ #
6
+ # \Deprecation specifies the API used by \Rails to deprecate methods, instance variables, objects, and constants. It's
7
+ # also available for gems or applications.
8
+ #
9
+ # For a gem, use Deprecation.new to create a Deprecation object and store it in your module or class (in order for
10
+ # users to be able to configure it).
11
+ #
12
+ # module MyLibrary
13
+ # def self.deprecator
14
+ # @deprecator ||= ActiveSupport::Deprecation.new("2.0", "MyLibrary")
15
+ # end
16
+ # end
17
+ #
18
+ # For a Railtie or Engine, you may also want to add it to the application's deprecators, so that the application's
19
+ # configuration can be applied to it.
20
+ #
21
+ # module MyLibrary
22
+ # class Railtie < Rails::Railtie
23
+ # initializer "my_library.deprecator" do |app|
24
+ # app.deprecators[:my_library] = MyLibrary.deprecator
25
+ # end
26
+ # end
27
+ # end
28
+ #
29
+ # With the above initializer, configuration settings like the following will affect +MyLibrary.deprecator+:
30
+ #
31
+ # # in config/environments/test.rb
32
+ # config.active_support.deprecation = :raise
8
33
  class Deprecation
9
34
  # active_support.rb sets an autoload for ActiveSupport::Deprecation.
10
35
  #
@@ -14,23 +39,28 @@ module ActiveSupport
14
39
  # a circular require warning for active_support/deprecation.rb.
15
40
  #
16
41
  # So, we define the constant first, and load dependencies later.
17
- require "active_support/deprecation/instance_delegator"
18
42
  require "active_support/deprecation/behaviors"
19
43
  require "active_support/deprecation/reporting"
20
44
  require "active_support/deprecation/disallowed"
21
45
  require "active_support/deprecation/constant_accessor"
22
46
  require "active_support/deprecation/method_wrappers"
23
47
  require "active_support/deprecation/proxy_wrappers"
48
+ require "active_support/deprecation/deprecators"
24
49
  require "active_support/core_ext/module/deprecation"
25
50
  require "concurrent/atomic/thread_local_var"
26
51
 
27
- include Singleton
28
- include InstanceDelegator
29
52
  include Behavior
30
53
  include Reporting
31
54
  include Disallowed
32
55
  include MethodWrapper
33
56
 
57
+ MUTEX = Mutex.new # :nodoc:
58
+ private_constant :MUTEX
59
+
60
+ def self._instance # :nodoc:
61
+ @_instance ||= MUTEX.synchronize { @_instance ||= new }
62
+ end
63
+
34
64
  # The version number in which the deprecated behavior will be removed, by default.
35
65
  attr_accessor :deprecation_horizon
36
66
 
@@ -38,13 +68,13 @@ module ActiveSupport
38
68
  # and the second is a library name.
39
69
  #
40
70
  # ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
41
- def initialize(deprecation_horizon = "7.1", gem_name = "Rails")
71
+ def initialize(deprecation_horizon = "8.0", gem_name = "Rails")
42
72
  self.gem_name = gem_name
43
73
  self.deprecation_horizon = deprecation_horizon
44
74
  # By default, warnings are not silenced and debugging is off.
45
75
  self.silenced = false
46
76
  self.debug = false
47
- @silenced_thread = Concurrent::ThreadLocalVar.new(false)
77
+ @silence_counter = Concurrent::ThreadLocalVar.new(0)
48
78
  @explicitly_allowed_warnings = Concurrent::ThreadLocalVar.new(nil)
49
79
  end
50
80
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ def self.deprecator # :nodoc:
5
+ ActiveSupport::Deprecation._instance
6
+ end
7
+ end
@@ -1,221 +1,112 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "weakref"
4
- require "active_support/ruby_features"
5
4
 
6
5
  module ActiveSupport
6
+ # = Active Support Descendants Tracker
7
+ #
7
8
  # This module provides an internal implementation to track descendants
8
- # which is faster than iterating through ObjectSpace.
9
+ # which is faster than iterating through +ObjectSpace+.
10
+ #
11
+ # However Ruby 3.1 provide a fast native +Class#subclasses+ method,
12
+ # so if you know your code won't be executed on older rubies, including
13
+ # +ActiveSupport::DescendantsTracker+ does not provide any benefit.
9
14
  module DescendantsTracker
10
- class << self
11
- def direct_descendants(klass)
12
- ActiveSupport::Deprecation.warn(<<~MSG)
13
- ActiveSupport::DescendantsTracker.direct_descendants is deprecated and will be removed in Rails 7.1.
14
- Use ActiveSupport::DescendantsTracker.subclasses instead.
15
- MSG
16
- subclasses(klass)
17
- end
18
- end
19
-
20
15
  @clear_disabled = false
21
16
 
22
- if RubyFeatures::CLASS_SUBCLASSES
23
- @@excluded_descendants = if RUBY_ENGINE == "ruby"
24
- # On MRI `ObjectSpace::WeakMap` keys are weak references.
25
- # So we can simply use WeakMap as a `Set`.
26
- ObjectSpace::WeakMap.new
27
- else
28
- # On TruffleRuby `ObjectSpace::WeakMap` keys are strong references.
29
- # So we use `object_id` as a key and the actual object as a value.
30
- #
31
- # JRuby for now doesn't have Class#descendant, but when it will, it will likely
32
- # have the same WeakMap semantic than Truffle so we future proof this as much as possible.
33
- class WeakSet # :nodoc:
34
- def initialize
35
- @map = ObjectSpace::WeakMap.new
36
- end
37
-
38
- def [](object)
39
- @map.key?(object.object_id)
40
- end
17
+ if RUBY_ENGINE == "ruby"
18
+ # On MRI `ObjectSpace::WeakMap` keys are weak references.
19
+ # So we can simply use WeakMap as a `Set`.
20
+ class WeakSet < ObjectSpace::WeakMap # :nodoc:
21
+ alias_method :to_a, :keys
41
22
 
42
- def []=(object, _present)
43
- @map[object.object_id] = object
44
- end
23
+ def <<(object)
24
+ self[object] = true
45
25
  end
46
- WeakSet.new
47
26
  end
48
-
49
- class << self
50
- def disable_clear! # :nodoc:
51
- unless @clear_disabled
52
- @clear_disabled = true
53
- remove_method(:subclasses)
54
- remove_method(:descendants)
55
- @@excluded_descendants = nil
56
- end
27
+ else
28
+ # On TruffleRuby `ObjectSpace::WeakMap` keys are strong references.
29
+ # So we use `object_id` as a key and the actual object as a value.
30
+ #
31
+ # JRuby for now doesn't have Class#descendant, but when it will, it will likely
32
+ # have the same WeakMap semantic than Truffle so we future proof this as much as possible.
33
+ class WeakSet # :nodoc:
34
+ def initialize
35
+ @map = ObjectSpace::WeakMap.new
57
36
  end
58
37
 
59
- def subclasses(klass)
60
- klass.subclasses
38
+ def [](object)
39
+ @map.key?(object.object_id)
61
40
  end
41
+ alias_method :include?, :[]
62
42
 
63
- def descendants(klass)
64
- klass.descendants
43
+ def []=(object, _present)
44
+ @map[object.object_id] = object
65
45
  end
66
46
 
67
- def clear(classes) # :nodoc:
68
- raise "DescendantsTracker.clear was disabled because config.cache_classes = true" if @clear_disabled
69
-
70
- classes.each do |klass|
71
- @@excluded_descendants[klass] = true
72
- klass.descendants.each do |descendant|
73
- @@excluded_descendants[descendant] = true
74
- end
75
- end
47
+ def to_a
48
+ @map.values
76
49
  end
77
50
 
78
- def native? # :nodoc:
79
- true
51
+ def <<(object)
52
+ self[object] = true
80
53
  end
81
54
  end
55
+ end
56
+ @excluded_descendants = WeakSet.new
82
57
 
58
+ module ReloadedClassesFiltering # :nodoc:
83
59
  def subclasses
84
- subclasses = super
85
- subclasses.reject! { |d| @@excluded_descendants[d] }
86
- subclasses
60
+ DescendantsTracker.reject!(super)
87
61
  end
88
62
 
89
63
  def descendants
90
- descendants = super
91
- descendants.reject! { |d| @@excluded_descendants[d] }
92
- descendants
93
- end
94
-
95
- def direct_descendants
96
- ActiveSupport::Deprecation.warn(<<~MSG)
97
- ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
98
- Use #subclasses instead.
99
- MSG
100
- subclasses
64
+ DescendantsTracker.reject!(super)
101
65
  end
102
- else
103
- @@direct_descendants = {}
66
+ end
104
67
 
105
- class << self
106
- def disable_clear! # :nodoc:
68
+ class << self
69
+ def disable_clear! # :nodoc:
70
+ unless @clear_disabled
107
71
  @clear_disabled = true
72
+ ReloadedClassesFiltering.remove_method(:subclasses)
73
+ ReloadedClassesFiltering.remove_method(:descendants)
74
+ @excluded_descendants = nil
108
75
  end
76
+ end
109
77
 
110
- def subclasses(klass)
111
- descendants = @@direct_descendants[klass]
112
- descendants ? descendants.to_a : []
113
- end
114
-
115
- def descendants(klass)
116
- arr = []
117
- accumulate_descendants(klass, arr)
118
- arr
119
- end
78
+ def clear(classes) # :nodoc:
79
+ raise "DescendantsTracker.clear was disabled because config.enable_reloading is false" if @clear_disabled
120
80
 
121
- def clear(classes) # :nodoc:
122
- raise "DescendantsTracker.clear was disabled because config.cache_classes = true" if @clear_disabled
123
-
124
- @@direct_descendants.each do |klass, direct_descendants_of_klass|
125
- if classes.member?(klass)
126
- @@direct_descendants.delete(klass)
127
- else
128
- direct_descendants_of_klass.reject! do |direct_descendant_of_class|
129
- classes.member?(direct_descendant_of_class)
130
- end
131
- end
81
+ classes.each do |klass|
82
+ @excluded_descendants << klass
83
+ klass.descendants.each do |descendant|
84
+ @excluded_descendants << descendant
132
85
  end
133
86
  end
134
-
135
- def native? # :nodoc:
136
- false
137
- end
138
-
139
- # This is the only method that is not thread safe, but is only ever called
140
- # during the eager loading phase.
141
- def store_inherited(klass, descendant)
142
- (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
143
- end
144
-
145
- private
146
- def accumulate_descendants(klass, acc)
147
- if direct_descendants = @@direct_descendants[klass]
148
- direct_descendants.each do |direct_descendant|
149
- acc << direct_descendant
150
- accumulate_descendants(direct_descendant, acc)
151
- end
152
- end
153
- end
154
- end
155
-
156
- def inherited(base)
157
- DescendantsTracker.store_inherited(self, base)
158
- super
159
87
  end
160
88
 
161
- def direct_descendants
162
- ActiveSupport::Deprecation.warn(<<~MSG)
163
- ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
164
- Use #subclasses instead.
165
- MSG
166
- DescendantsTracker.subclasses(self)
89
+ def reject!(classes) # :nodoc:
90
+ if @excluded_descendants
91
+ classes.reject! { |d| @excluded_descendants.include?(d) }
92
+ end
93
+ classes
167
94
  end
95
+ end
168
96
 
169
- def subclasses
170
- DescendantsTracker.subclasses(self)
97
+ class << self
98
+ def subclasses(klass)
99
+ klass.subclasses
171
100
  end
172
101
 
173
- def descendants
174
- DescendantsTracker.descendants(self)
102
+ def descendants(klass)
103
+ klass.descendants
175
104
  end
105
+ end
176
106
 
177
- # DescendantsArray is an array that contains weak references to classes.
178
- class DescendantsArray # :nodoc:
179
- include Enumerable
180
-
181
- def initialize
182
- @refs = []
183
- end
184
-
185
- def initialize_copy(orig)
186
- @refs = @refs.dup
187
- end
188
-
189
- def <<(klass)
190
- @refs << WeakRef.new(klass)
191
- end
192
-
193
- def each
194
- @refs.reject! do |ref|
195
- yield ref.__getobj__
196
- false
197
- rescue WeakRef::RefError
198
- true
199
- end
200
- self
201
- end
202
-
203
- def refs_size
204
- @refs.size
205
- end
206
-
207
- def cleanup!
208
- @refs.delete_if { |ref| !ref.weakref_alive? }
209
- end
210
-
211
- def reject!
212
- @refs.reject! do |ref|
213
- yield ref.__getobj__
214
- rescue WeakRef::RefError
215
- true
216
- end
217
- end
218
- end
107
+ def descendants
108
+ subclasses = DescendantsTracker.reject!(self.subclasses)
109
+ subclasses.concat(subclasses.flat_map(&:descendants))
219
110
  end
220
111
  end
221
112
  end
@@ -102,12 +102,12 @@ module ActiveSupport
102
102
  raise_parsing_error("is empty duration") if parts.empty?
103
103
 
104
104
  # Mixing any of Y, M, D with W is invalid.
105
- if parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any?
105
+ if parts.key?(:weeks) && parts.keys.intersect?(DATE_COMPONENTS)
106
106
  raise_parsing_error("mixing weeks with other date parts not allowed")
107
107
  end
108
108
 
109
109
  # Specifying an empty T part is invalid.
110
- if mode == :time && (parts.keys & TIME_COMPONENTS).empty?
110
+ if mode == :time && !parts.keys.intersect?(TIME_COMPONENTS)
111
111
  raise_parsing_error("time part marker is present but time part is empty")
112
112
  end
113
113
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/object/blank"
4
-
5
3
  module ActiveSupport
6
4
  class Duration
7
5
  # Serializes duration to string according to ISO 8601 Duration format.
@@ -37,7 +35,6 @@ module ActiveSupport
37
35
  # Return pair of duration's parts and whole duration sign.
38
36
  # Parts are summarized (as they can become repetitive due to addition, etc).
39
37
  # Zero parts are removed as not significant.
40
- # If all parts are negative it will negate all of them and return minus as a sign.
41
38
  def normalize
42
39
  parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
43
40
  p[k] += v unless v.zero?
@@ -52,7 +49,7 @@ module ActiveSupport
52
49
  end
53
50
 
54
51
  def week_mixed_with_date?(parts)
55
- parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any?
52
+ parts.key?(:weeks) && parts.keys.intersect?(DATE_COMPONENTS)
56
53
  end
57
54
 
58
55
  def format_seconds(seconds)
@@ -3,9 +3,10 @@
3
3
  require "active_support/core_ext/array/conversions"
4
4
  require "active_support/core_ext/module/delegation"
5
5
  require "active_support/core_ext/object/acts_like"
6
- require "active_support/core_ext/string/filters"
7
6
 
8
7
  module ActiveSupport
8
+ # = Active Support \Duration
9
+ #
9
10
  # Provides accurate date and time measurements using Date#advance and
10
11
  # Time#advance, respectively. It mainly supports the methods on Numeric.
11
12
  #
@@ -13,7 +14,7 @@ module ActiveSupport
13
14
  class Duration
14
15
  class Scalar < Numeric # :nodoc:
15
16
  attr_reader :value
16
- delegate :to_i, :to_f, :to_s, to: :value
17
+ delegate :to_i, :to_f, :to_s, to: :@value
17
18
 
18
19
  def initialize(value)
19
20
  @value = value
@@ -220,6 +221,8 @@ module ActiveSupport
220
221
  end
221
222
  end
222
223
 
224
+ Delegation.generate(self, [:to_f, :positive?, :negative?, :zero?, :abs], to: :@value, as: Integer, nilable: false)
225
+
223
226
  def initialize(value, parts, variable = nil) # :nodoc:
224
227
  @value, @parts = value, parts
225
228
  @parts.reject! { |k, v| v.zero? } unless value == 0
@@ -231,7 +234,10 @@ module ActiveSupport
231
234
  end
232
235
  end
233
236
 
234
- # Returns a copy of the parts hash that defines the duration
237
+ # Returns a copy of the parts hash that defines the duration.
238
+ #
239
+ # 5.minutes.parts # => {:minutes=>5}
240
+ # 3.years.parts # => {:years=>3}
235
241
  def parts
236
242
  @parts.dup
237
243
  end
@@ -365,8 +371,8 @@ module ActiveSupport
365
371
  # 1.year.to_i # => 31556952
366
372
  #
367
373
  # In such cases, Ruby's core
368
- # Date[https://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
369
- # Time[https://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
374
+ # Date[https://docs.ruby-lang.org/en/master/Date.html] and
375
+ # Time[https://docs.ruby-lang.org/en/master/Time.html] should be used for precision
370
376
  # date and time arithmetic.
371
377
  def to_i
372
378
  @value.to_i
@@ -503,8 +509,8 @@ module ActiveSupport
503
509
  value.respond_to?(method)
504
510
  end
505
511
 
506
- def method_missing(method, *args, &block)
507
- value.public_send(method, *args, &block)
512
+ def method_missing(...)
513
+ value.public_send(...)
508
514
  end
509
515
 
510
516
  def raise_type_error(other)