activesupport 7.0.4 → 7.1.5.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1076 -230
  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 +2 -0
  7. data/lib/active_support/backtrace_cleaner.rb +30 -5
  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 +37 -10
  14. data/lib/active_support/cache/mem_cache_store.rb +100 -76
  15. data/lib/active_support/cache/memory_store.rb +78 -24
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +153 -141
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +29 -14
  20. data/lib/active_support/cache.rb +333 -253
  21. data/lib/active_support/callbacks.rb +44 -21
  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 +10 -0
  27. data/lib/active_support/core_ext/array/conversions.rb +2 -1
  28. data/lib/active_support/core_ext/array.rb +0 -1
  29. data/lib/active_support/core_ext/class/subclasses.rb +13 -10
  30. data/lib/active_support/core_ext/date/calculations.rb +15 -0
  31. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  32. data/lib/active_support/core_ext/date.rb +0 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  34. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  35. data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
  36. data/lib/active_support/core_ext/date_time.rb +0 -1
  37. data/lib/active_support/core_ext/digest/uuid.rb +1 -10
  38. data/lib/active_support/core_ext/enumerable.rb +8 -75
  39. data/lib/active_support/core_ext/erb/util.rb +196 -0
  40. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  41. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  42. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  43. data/lib/active_support/core_ext/hash/keys.rb +3 -3
  44. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  45. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  46. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  47. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  48. data/lib/active_support/core_ext/module/delegation.rb +81 -37
  49. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  50. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  51. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  52. data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
  53. data/lib/active_support/core_ext/numeric.rb +0 -1
  54. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  55. data/lib/active_support/core_ext/object/duplicable.rb +25 -16
  56. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  57. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  58. data/lib/active_support/core_ext/object/json.rb +16 -6
  59. data/lib/active_support/core_ext/object/to_query.rb +0 -2
  60. data/lib/active_support/core_ext/object/with.rb +44 -0
  61. data/lib/active_support/core_ext/object/with_options.rb +9 -9
  62. data/lib/active_support/core_ext/object.rb +1 -0
  63. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  64. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  65. data/lib/active_support/core_ext/pathname.rb +1 -0
  66. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  67. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  68. data/lib/active_support/core_ext/range.rb +1 -2
  69. data/lib/active_support/core_ext/securerandom.rb +24 -12
  70. data/lib/active_support/core_ext/string/filters.rb +20 -14
  71. data/lib/active_support/core_ext/string/indent.rb +1 -1
  72. data/lib/active_support/core_ext/string/inflections.rb +16 -9
  73. data/lib/active_support/core_ext/string/output_safety.rb +42 -174
  74. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  75. data/lib/active_support/core_ext/time/calculations.rb +22 -2
  76. data/lib/active_support/core_ext/time/conversions.rb +2 -2
  77. data/lib/active_support/core_ext/time/zones.rb +7 -8
  78. data/lib/active_support/core_ext/time.rb +0 -1
  79. data/lib/active_support/current_attributes.rb +15 -6
  80. data/lib/active_support/deep_mergeable.rb +53 -0
  81. data/lib/active_support/dependencies/autoload.rb +17 -12
  82. data/lib/active_support/deprecation/behaviors.rb +65 -42
  83. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  84. data/lib/active_support/deprecation/deprecators.rb +104 -0
  85. data/lib/active_support/deprecation/disallowed.rb +6 -8
  86. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  87. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  88. data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
  89. data/lib/active_support/deprecation/reporting.rb +43 -26
  90. data/lib/active_support/deprecation.rb +32 -5
  91. data/lib/active_support/deprecator.rb +7 -0
  92. data/lib/active_support/descendants_tracker.rb +104 -132
  93. data/lib/active_support/duration/iso8601_serializer.rb +0 -2
  94. data/lib/active_support/duration.rb +2 -1
  95. data/lib/active_support/encrypted_configuration.rb +63 -11
  96. data/lib/active_support/encrypted_file.rb +16 -12
  97. data/lib/active_support/environment_inquirer.rb +22 -2
  98. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  99. data/lib/active_support/error_reporter.rb +121 -35
  100. data/lib/active_support/evented_file_update_checker.rb +17 -2
  101. data/lib/active_support/execution_wrapper.rb +4 -4
  102. data/lib/active_support/file_update_checker.rb +4 -2
  103. data/lib/active_support/fork_tracker.rb +10 -2
  104. data/lib/active_support/gem_version.rb +4 -4
  105. data/lib/active_support/gzip.rb +2 -0
  106. data/lib/active_support/hash_with_indifferent_access.rb +35 -17
  107. data/lib/active_support/html_safe_translation.rb +16 -6
  108. data/lib/active_support/i18n.rb +1 -1
  109. data/lib/active_support/i18n_railtie.rb +20 -13
  110. data/lib/active_support/inflector/inflections.rb +2 -0
  111. data/lib/active_support/inflector/methods.rb +28 -18
  112. data/lib/active_support/inflector/transliterate.rb +3 -1
  113. data/lib/active_support/isolated_execution_state.rb +26 -22
  114. data/lib/active_support/json/decoding.rb +2 -1
  115. data/lib/active_support/json/encoding.rb +25 -43
  116. data/lib/active_support/key_generator.rb +9 -1
  117. data/lib/active_support/lazy_load_hooks.rb +7 -5
  118. data/lib/active_support/locale/en.yml +2 -0
  119. data/lib/active_support/log_subscriber.rb +85 -33
  120. data/lib/active_support/logger.rb +9 -60
  121. data/lib/active_support/logger_thread_safe_level.rb +10 -24
  122. data/lib/active_support/message_encryptor.rb +197 -53
  123. data/lib/active_support/message_encryptors.rb +141 -0
  124. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  125. data/lib/active_support/message_pack/extensions.rb +292 -0
  126. data/lib/active_support/message_pack/serializer.rb +63 -0
  127. data/lib/active_support/message_pack.rb +50 -0
  128. data/lib/active_support/message_verifier.rb +212 -93
  129. data/lib/active_support/message_verifiers.rb +135 -0
  130. data/lib/active_support/messages/codec.rb +65 -0
  131. data/lib/active_support/messages/metadata.rb +111 -45
  132. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  133. data/lib/active_support/messages/rotator.rb +34 -32
  134. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  135. data/lib/active_support/multibyte/chars.rb +2 -0
  136. data/lib/active_support/multibyte/unicode.rb +9 -37
  137. data/lib/active_support/notifications/fanout.rb +245 -81
  138. data/lib/active_support/notifications/instrumenter.rb +87 -22
  139. data/lib/active_support/notifications.rb +3 -3
  140. data/lib/active_support/number_helper/number_converter.rb +14 -5
  141. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  142. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  143. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  144. data/lib/active_support/number_helper.rb +379 -317
  145. data/lib/active_support/ordered_hash.rb +3 -3
  146. data/lib/active_support/ordered_options.rb +14 -0
  147. data/lib/active_support/parameter_filter.rb +103 -84
  148. data/lib/active_support/proxy_object.rb +2 -0
  149. data/lib/active_support/railtie.rb +33 -21
  150. data/lib/active_support/reloader.rb +12 -4
  151. data/lib/active_support/rescuable.rb +2 -0
  152. data/lib/active_support/secure_compare_rotator.rb +16 -9
  153. data/lib/active_support/string_inquirer.rb +3 -1
  154. data/lib/active_support/subscriber.rb +9 -27
  155. data/lib/active_support/syntax_error_proxy.rb +60 -0
  156. data/lib/active_support/tagged_logging.rb +64 -24
  157. data/lib/active_support/test_case.rb +153 -6
  158. data/lib/active_support/testing/assertions.rb +26 -10
  159. data/lib/active_support/testing/autorun.rb +0 -2
  160. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  161. data/lib/active_support/testing/deprecation.rb +25 -25
  162. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  163. data/lib/active_support/testing/isolation.rb +29 -28
  164. data/lib/active_support/testing/method_call_assertions.rb +21 -8
  165. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  166. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  167. data/lib/active_support/testing/stream.rb +1 -1
  168. data/lib/active_support/testing/strict_warnings.rb +39 -0
  169. data/lib/active_support/testing/time_helpers.rb +37 -15
  170. data/lib/active_support/time_with_zone.rb +8 -37
  171. data/lib/active_support/values/time_zone.rb +18 -7
  172. data/lib/active_support/version.rb +1 -1
  173. data/lib/active_support/xml_mini/jdom.rb +3 -10
  174. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  175. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  176. data/lib/active_support/xml_mini/rexml.rb +1 -1
  177. data/lib/active_support/xml_mini.rb +2 -2
  178. data/lib/active_support.rb +14 -3
  179. metadata +148 -19
  180. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  181. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
  182. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
  183. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  184. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
  185. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
  186. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  187. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
  188. data/lib/active_support/core_ext/uri.rb +0 -5
  189. data/lib/active_support/per_thread_registry.rb +0 -65
@@ -25,11 +25,10 @@ module ActiveSupport
25
25
  end
26
26
  end
27
27
 
28
- # DeprecatedObjectProxy transforms an object into a deprecated one. It
29
- # takes an object, a deprecation message, and optionally a deprecator. The
30
- # deprecator defaults to +ActiveSupport::Deprecator+ if none is specified.
28
+ # DeprecatedObjectProxy transforms an object into a deprecated one. It takes an object, a deprecation message, and
29
+ # a deprecator.
31
30
  #
32
- # deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated")
31
+ # deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated", ActiveSupport::Deprecation.new)
33
32
  # # => #<Object:0x007fb9b34c34b0>
34
33
  #
35
34
  # deprecated_object.to_s
@@ -37,10 +36,11 @@ module ActiveSupport
37
36
  # (Backtrace)
38
37
  # # => "#<Object:0x007fb9b34c34b0>"
39
38
  class DeprecatedObjectProxy < DeprecationProxy
40
- def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance)
39
+ def initialize(object, message, deprecator = nil)
41
40
  @object = object
42
41
  @message = message
43
- @deprecator = deprecator
42
+ ActiveSupport.deprecator.warn("DeprecatedObjectProxy without a deprecator is deprecated") unless deprecator
43
+ @deprecator = deprecator || ActiveSupport::Deprecation._instance
44
44
  end
45
45
 
46
46
  private
@@ -53,15 +53,15 @@ module ActiveSupport
53
53
  end
54
54
  end
55
55
 
56
- # DeprecatedInstanceVariableProxy transforms an instance variable into a
57
- # deprecated one. It takes an instance of a class, a method on that class
58
- # and an instance variable. It optionally takes a deprecator as the last
59
- # argument. The deprecator defaults to +ActiveSupport::Deprecator+ if none
60
- # is specified.
56
+ # DeprecatedInstanceVariableProxy transforms an instance variable into a deprecated one. It takes an instance of a
57
+ # class, a method on that class, an instance variable, and a deprecator as the last argument.
58
+ #
59
+ # Trying to use the deprecated instance variable will result in a deprecation warning, pointing to the method as a
60
+ # replacement.
61
61
  #
62
62
  # class Example
63
63
  # def initialize
64
- # @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request)
64
+ # @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, ActiveSupport::Deprecation.new)
65
65
  # @_request = :special_request
66
66
  # end
67
67
  #
@@ -86,11 +86,12 @@ module ActiveSupport
86
86
  # example.request.to_s
87
87
  # # => "special_request"
88
88
  class DeprecatedInstanceVariableProxy < DeprecationProxy
89
- def initialize(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance)
89
+ def initialize(instance, method, var = "@#{method}", deprecator = nil)
90
90
  @instance = instance
91
91
  @method = method
92
92
  @var = var
93
- @deprecator = deprecator
93
+ ActiveSupport.deprecator.warn("DeprecatedInstanceVariableProxy without a deprecator is deprecated") unless deprecator
94
+ @deprecator = deprecator || ActiveSupport::Deprecation._instance
94
95
  end
95
96
 
96
97
  private
@@ -103,18 +104,16 @@ module ActiveSupport
103
104
  end
104
105
  end
105
106
 
106
- # DeprecatedConstantProxy transforms a constant into a deprecated one. It
107
- # takes the names of an old (deprecated) constant and of a new constant
108
- # (both in string form) and optionally a deprecator. The deprecator defaults
109
- # to +ActiveSupport::Deprecator+ if none is specified. The deprecated constant
110
- # now returns the value of the new one.
107
+ # DeprecatedConstantProxy transforms a constant into a deprecated one. It takes the full names of an old
108
+ # (deprecated) constant and of a new constant (both in string form) and a deprecator. The deprecated constant now
109
+ # returns the value of the new one.
111
110
  #
112
111
  # PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
113
112
  #
114
113
  # # (In a later update, the original implementation of `PLANETS` has been removed.)
115
114
  #
116
115
  # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
117
- # PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
116
+ # PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("PLANETS", "PLANETS_POST_2006", ActiveSupport::Deprecation.new)
118
117
  #
119
118
  # PLANETS.map { |planet| planet.capitalize }
120
119
  # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
@@ -128,12 +127,13 @@ module ActiveSupport
128
127
  super
129
128
  end
130
129
 
131
- def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
130
+ def initialize(old_const, new_const, deprecator = nil, message: "#{old_const} is deprecated! Use #{new_const} instead.")
132
131
  Kernel.require "active_support/inflector/methods"
133
132
 
134
133
  @old_const = old_const
135
134
  @new_const = new_const
136
- @deprecator = deprecator
135
+ ActiveSupport.deprecator.warn("DeprecatedConstantProxy without a deprecator is deprecated") unless deprecator
136
+ @deprecator = deprecator || ActiveSupport::Deprecation._instance
137
137
  @message = message
138
138
  end
139
139
 
@@ -158,6 +158,21 @@ module ActiveSupport
158
158
  target.class
159
159
  end
160
160
 
161
+ def append_features(base)
162
+ @deprecator.warn(@message, caller_locations)
163
+ base.include(target)
164
+ end
165
+
166
+ def prepend_features(base)
167
+ @deprecator.warn(@message, caller_locations)
168
+ base.prepend(target)
169
+ end
170
+
171
+ def extended(base)
172
+ @deprecator.warn(@message, caller_locations)
173
+ base.extend(target)
174
+ end
175
+
161
176
  private
162
177
  def target
163
178
  ActiveSupport::Inflector.constantize(@new_const.to_s)
@@ -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,10 +138,13 @@ 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]
@@ -136,7 +152,7 @@ module ActiveSupport
136
152
 
137
153
  def _extract_callstack(callstack)
138
154
  warn "Please pass `caller_locations` to the deprecation API" if $VERBOSE
139
- offending_line = callstack.find { |line| !ignored_callstack(line) } || callstack.first
155
+ offending_line = callstack.find { |line| !ignored_callstack?(line) } || callstack.first
140
156
 
141
157
  if offending_line
142
158
  if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
@@ -147,10 +163,11 @@ module ActiveSupport
147
163
  end
148
164
  end
149
165
 
150
- RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/"
166
+ RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/" # :nodoc:
167
+ LIB_DIR = RbConfig::CONFIG["libdir"] # :nodoc:
151
168
 
152
- def ignored_callstack(path)
153
- path.start_with?(RAILS_GEM_ROOT) || path.start_with?(RbConfig::CONFIG["rubylibdir"])
169
+ def ignored_callstack?(path)
170
+ path.start_with?(RAILS_GEM_ROOT, LIB_DIR)
154
171
  end
155
172
  end
156
173
  end
@@ -3,8 +3,35 @@
3
3
  require "singleton"
4
4
 
5
5
  module ActiveSupport
6
- # \Deprecation specifies the API used by Rails to deprecate methods, instance
7
- # variables, objects, and constants.
6
+ # = Active Support \Deprecation
7
+ #
8
+ # \Deprecation specifies the API used by \Rails to deprecate methods, instance variables, objects, and constants. It's
9
+ # also available for gems or applications.
10
+ #
11
+ # For a gem, use Deprecation.new to create a Deprecation object and store it in your module or class (in order for
12
+ # users to be able to configure it).
13
+ #
14
+ # module MyLibrary
15
+ # def self.deprecator
16
+ # @deprecator ||= ActiveSupport::Deprecation.new("2.0", "MyLibrary")
17
+ # end
18
+ # end
19
+ #
20
+ # For a Railtie or Engine, you may also want to add it to the application's deprecators, so that the application's
21
+ # configuration can be applied to it.
22
+ #
23
+ # module MyLibrary
24
+ # class Railtie < Rails::Railtie
25
+ # initializer "my_library.deprecator" do |app|
26
+ # app.deprecators[:my_library] = MyLibrary.deprecator
27
+ # end
28
+ # end
29
+ # end
30
+ #
31
+ # With the above initializer, configuration settings like the following will affect +MyLibrary.deprecator+:
32
+ #
33
+ # # in config/environments/test.rb
34
+ # config.active_support.deprecation = :raise
8
35
  class Deprecation
9
36
  # active_support.rb sets an autoload for ActiveSupport::Deprecation.
10
37
  #
@@ -21,10 +48,10 @@ module ActiveSupport
21
48
  require "active_support/deprecation/constant_accessor"
22
49
  require "active_support/deprecation/method_wrappers"
23
50
  require "active_support/deprecation/proxy_wrappers"
51
+ require "active_support/deprecation/deprecators"
24
52
  require "active_support/core_ext/module/deprecation"
25
53
  require "concurrent/atomic/thread_local_var"
26
54
 
27
- include Singleton
28
55
  include InstanceDelegator
29
56
  include Behavior
30
57
  include Reporting
@@ -38,13 +65,13 @@ module ActiveSupport
38
65
  # and the second is a library name.
39
66
  #
40
67
  # ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
41
- def initialize(deprecation_horizon = "7.1", gem_name = "Rails")
68
+ def initialize(deprecation_horizon = "7.2", gem_name = "Rails")
42
69
  self.gem_name = gem_name
43
70
  self.deprecation_horizon = deprecation_horizon
44
71
  # By default, warnings are not silenced and debugging is off.
45
72
  self.silenced = false
46
73
  self.debug = false
47
- @silenced_thread = Concurrent::ThreadLocalVar.new(false)
74
+ @silence_counter = Concurrent::ThreadLocalVar.new(0)
48
75
  @explicitly_allowed_warnings = Concurrent::ThreadLocalVar.new(nil)
49
76
  end
50
77
  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
@@ -4,174 +4,116 @@ require "weakref"
4
4
  require "active_support/ruby_features"
5
5
 
6
6
  module ActiveSupport
7
+ # = Active Support Descendants Tracker
8
+ #
7
9
  # This module provides an internal implementation to track descendants
8
- # which is faster than iterating through ObjectSpace.
10
+ # which is faster than iterating through +ObjectSpace+.
11
+ #
12
+ # However Ruby 3.1 provide a fast native +Class#subclasses+ method,
13
+ # so if you know your code won't be executed on older rubies, including
14
+ # +ActiveSupport::DescendantsTracker+ does not provide any benefit.
9
15
  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
16
  @clear_disabled = false
21
17
 
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
18
+ if RUBY_ENGINE == "ruby"
19
+ # On MRI `ObjectSpace::WeakMap` keys are weak references.
20
+ # So we can simply use WeakMap as a `Set`.
21
+ class WeakSet < ObjectSpace::WeakMap # :nodoc:
22
+ alias_method :to_a, :keys
37
23
 
38
- def [](object)
39
- @map.key?(object.object_id)
40
- end
41
-
42
- def []=(object, _present)
43
- @map[object.object_id] = object
44
- end
24
+ def <<(object)
25
+ self[object] = true
45
26
  end
46
- WeakSet.new
47
27
  end
48
-
49
- class << self
50
- def disable_clear! # :nodoc:
51
- unless @clear_disabled
52
- @clear_disabled = true
53
- remove_method(:subclasses)
54
- @@excluded_descendants = nil
55
- end
28
+ else
29
+ # On TruffleRuby `ObjectSpace::WeakMap` keys are strong references.
30
+ # So we use `object_id` as a key and the actual object as a value.
31
+ #
32
+ # JRuby for now doesn't have Class#descendant, but when it will, it will likely
33
+ # have the same WeakMap semantic than Truffle so we future proof this as much as possible.
34
+ class WeakSet # :nodoc:
35
+ def initialize
36
+ @map = ObjectSpace::WeakMap.new
56
37
  end
57
38
 
58
- def subclasses(klass)
59
- klass.subclasses
39
+ def [](object)
40
+ @map.key?(object.object_id)
60
41
  end
42
+ alias_method :include?, :[]
61
43
 
62
- def descendants(klass)
63
- klass.descendants
44
+ def []=(object, _present)
45
+ @map[object.object_id] = object
64
46
  end
65
47
 
66
- def clear(classes) # :nodoc:
67
- raise "DescendantsTracker.clear was disabled because config.cache_classes = true" if @clear_disabled
68
-
69
- classes.each do |klass|
70
- @@excluded_descendants[klass] = true
71
- klass.descendants.each do |descendant|
72
- @@excluded_descendants[descendant] = true
73
- end
74
- end
48
+ def to_a
49
+ @map.values
75
50
  end
76
51
 
77
- def native? # :nodoc:
78
- true
52
+ def <<(object)
53
+ self[object] = true
79
54
  end
80
55
  end
56
+ end
57
+ @excluded_descendants = WeakSet.new
81
58
 
59
+ module ReloadedClassesFiltering # :nodoc:
82
60
  def subclasses
83
- subclasses = super
84
- subclasses.reject! { |d| @@excluded_descendants[d] }
85
- subclasses
61
+ DescendantsTracker.reject!(super)
86
62
  end
87
63
 
88
64
  def descendants
89
- subclasses.concat(subclasses.flat_map(&:descendants))
90
- end
91
-
92
- def direct_descendants
93
- ActiveSupport::Deprecation.warn(<<~MSG)
94
- ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
95
- Use #subclasses instead.
96
- MSG
97
- subclasses
65
+ DescendantsTracker.reject!(super)
98
66
  end
99
- else
100
- @@direct_descendants = {}
67
+ end
101
68
 
102
- class << self
103
- def disable_clear! # :nodoc:
69
+ class << self
70
+ def disable_clear! # :nodoc:
71
+ unless @clear_disabled
104
72
  @clear_disabled = true
73
+ ReloadedClassesFiltering.remove_method(:subclasses)
74
+ ReloadedClassesFiltering.remove_method(:descendants)
75
+ @excluded_descendants = nil
105
76
  end
77
+ end
106
78
 
107
- def subclasses(klass)
108
- descendants = @@direct_descendants[klass]
109
- descendants ? descendants.to_a : []
110
- end
79
+ def clear(classes) # :nodoc:
80
+ raise "DescendantsTracker.clear was disabled because config.enable_reloading is false" if @clear_disabled
111
81
 
112
- def descendants(klass)
113
- arr = []
114
- accumulate_descendants(klass, arr)
115
- arr
116
- end
117
-
118
- def clear(classes) # :nodoc:
119
- raise "DescendantsTracker.clear was disabled because config.cache_classes = true" if @clear_disabled
120
-
121
- @@direct_descendants.each do |klass, direct_descendants_of_klass|
122
- if classes.member?(klass)
123
- @@direct_descendants.delete(klass)
124
- else
125
- direct_descendants_of_klass.reject! do |direct_descendant_of_class|
126
- classes.member?(direct_descendant_of_class)
127
- end
128
- end
82
+ classes.each do |klass|
83
+ @excluded_descendants << klass
84
+ klass.descendants.each do |descendant|
85
+ @excluded_descendants << descendant
129
86
  end
130
87
  end
131
-
132
- def native? # :nodoc:
133
- false
134
- end
135
-
136
- # This is the only method that is not thread safe, but is only ever called
137
- # during the eager loading phase.
138
- def store_inherited(klass, descendant)
139
- (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
140
- end
141
-
142
- private
143
- def accumulate_descendants(klass, acc)
144
- if direct_descendants = @@direct_descendants[klass]
145
- direct_descendants.each do |direct_descendant|
146
- acc << direct_descendant
147
- accumulate_descendants(direct_descendant, acc)
148
- end
149
- end
150
- end
151
88
  end
152
89
 
153
- def inherited(base)
154
- DescendantsTracker.store_inherited(self, base)
155
- super
90
+ def reject!(classes) # :nodoc:
91
+ if @excluded_descendants
92
+ classes.reject! { |d| @excluded_descendants.include?(d) }
93
+ end
94
+ classes
156
95
  end
96
+ end
157
97
 
158
- def direct_descendants
159
- ActiveSupport::Deprecation.warn(<<~MSG)
160
- ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
161
- Use #subclasses instead.
162
- MSG
163
- DescendantsTracker.subclasses(self)
164
- end
98
+ if RubyFeatures::CLASS_SUBCLASSES
99
+ class << self
100
+ def subclasses(klass)
101
+ klass.subclasses
102
+ end
165
103
 
166
- def subclasses
167
- DescendantsTracker.subclasses(self)
104
+ def descendants(klass)
105
+ klass.descendants
106
+ end
168
107
  end
169
108
 
170
109
  def descendants
171
- DescendantsTracker.descendants(self)
110
+ subclasses = DescendantsTracker.reject!(self.subclasses)
111
+ subclasses.concat(subclasses.flat_map(&:descendants))
172
112
  end
173
-
113
+ else
174
114
  # DescendantsArray is an array that contains weak references to classes.
115
+ # Note: DescendantsArray is redundant with WeakSet, however WeakSet when used
116
+ # on Ruby 2.7 or 3.0 can trigger a Ruby crash: https://bugs.ruby-lang.org/issues/18928
175
117
  class DescendantsArray # :nodoc:
176
118
  include Enumerable
177
119
 
@@ -179,10 +121,6 @@ module ActiveSupport
179
121
  @refs = []
180
122
  end
181
123
 
182
- def initialize_copy(orig)
183
- @refs = @refs.dup
184
- end
185
-
186
124
  def <<(klass)
187
125
  @refs << WeakRef.new(klass)
188
126
  end
@@ -213,6 +151,40 @@ module ActiveSupport
213
151
  end
214
152
  end
215
153
  end
154
+
155
+ @direct_descendants = {}
156
+
157
+ class << self
158
+ def subclasses(klass)
159
+ descendants = @direct_descendants[klass]
160
+ descendants ? DescendantsTracker.reject!(descendants.to_a) : []
161
+ end
162
+
163
+ def descendants(klass)
164
+ subclasses = self.subclasses(klass)
165
+ subclasses.concat(subclasses.flat_map { |k| descendants(k) })
166
+ end
167
+
168
+ # This is the only method that is not thread safe, but is only ever called
169
+ # during the eager loading phase.
170
+ def store_inherited(klass, descendant) # :nodoc:
171
+ (@direct_descendants[klass] ||= DescendantsArray.new) << descendant
172
+ end
173
+ end
174
+
175
+ def subclasses
176
+ DescendantsTracker.subclasses(self)
177
+ end
178
+
179
+ def descendants
180
+ DescendantsTracker.descendants(self)
181
+ end
182
+
183
+ private
184
+ def inherited(base) # :nodoc:
185
+ DescendantsTracker.store_inherited(self, base)
186
+ super
187
+ end
216
188
  end
217
189
  end
218
190
  end
@@ -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.
@@ -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
  #