activesupport 6.0.3.4 → 6.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +371 -448
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_support.rb +13 -1
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +3 -3
  8. data/lib/active_support/benchmarkable.rb +1 -1
  9. data/lib/active_support/cache.rb +85 -44
  10. data/lib/active_support/cache/file_store.rb +4 -3
  11. data/lib/active_support/cache/mem_cache_store.rb +29 -18
  12. data/lib/active_support/cache/memory_store.rb +46 -26
  13. data/lib/active_support/cache/redis_cache_store.rb +27 -27
  14. data/lib/active_support/cache/strategy/local_cache.rb +21 -6
  15. data/lib/active_support/callbacks.rb +65 -56
  16. data/lib/active_support/concern.rb +46 -2
  17. data/lib/active_support/configurable.rb +3 -3
  18. data/lib/active_support/configuration_file.rb +46 -0
  19. data/lib/active_support/core_ext.rb +1 -1
  20. data/lib/active_support/core_ext/benchmark.rb +2 -2
  21. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  22. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  23. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  24. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  25. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  26. data/lib/active_support/core_ext/enumerable.rb +76 -4
  27. data/lib/active_support/core_ext/hash/conversions.rb +2 -2
  28. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  29. data/lib/active_support/core_ext/hash/except.rb +1 -1
  30. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  31. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  32. data/lib/active_support/core_ext/load_error.rb +1 -1
  33. data/lib/active_support/core_ext/marshal.rb +2 -0
  34. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  35. data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
  36. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
  37. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  38. data/lib/active_support/core_ext/module/delegation.rb +38 -28
  39. data/lib/active_support/core_ext/module/introspection.rb +1 -25
  40. data/lib/active_support/core_ext/name_error.rb +29 -2
  41. data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
  42. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  43. data/lib/active_support/core_ext/object/json.rb +13 -2
  44. data/lib/active_support/core_ext/object/try.rb +2 -2
  45. data/lib/active_support/core_ext/range/compare_range.rb +9 -3
  46. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  47. data/lib/active_support/core_ext/regexp.rb +8 -1
  48. data/lib/active_support/core_ext/string/access.rb +5 -24
  49. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  50. data/lib/active_support/core_ext/string/inflections.rb +38 -4
  51. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  52. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  53. data/lib/active_support/core_ext/string/output_safety.rb +10 -10
  54. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  55. data/lib/active_support/core_ext/symbol.rb +3 -0
  56. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  57. data/lib/active_support/core_ext/time/calculations.rb +27 -3
  58. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  59. data/lib/active_support/core_ext/uri.rb +5 -1
  60. data/lib/active_support/current_attributes.rb +7 -2
  61. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  62. data/lib/active_support/dependencies.rb +43 -19
  63. data/lib/active_support/deprecation.rb +6 -1
  64. data/lib/active_support/deprecation/behaviors.rb +15 -2
  65. data/lib/active_support/deprecation/disallowed.rb +56 -0
  66. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  67. data/lib/active_support/deprecation/method_wrappers.rb +3 -2
  68. data/lib/active_support/deprecation/proxy_wrappers.rb +3 -3
  69. data/lib/active_support/deprecation/reporting.rb +50 -7
  70. data/lib/active_support/descendants_tracker.rb +6 -2
  71. data/lib/active_support/duration.rb +71 -22
  72. data/lib/active_support/duration/iso8601_serializer.rb +15 -9
  73. data/lib/active_support/encrypted_file.rb +19 -2
  74. data/lib/active_support/environment_inquirer.rb +20 -0
  75. data/lib/active_support/evented_file_update_checker.rb +69 -133
  76. data/lib/active_support/fork_tracker.rb +62 -0
  77. data/lib/active_support/gem_version.rb +2 -2
  78. data/lib/active_support/hash_with_indifferent_access.rb +43 -24
  79. data/lib/active_support/i18n_railtie.rb +14 -19
  80. data/lib/active_support/inflector/inflections.rb +1 -2
  81. data/lib/active_support/inflector/methods.rb +35 -31
  82. data/lib/active_support/inflector/transliterate.rb +4 -4
  83. data/lib/active_support/json/decoding.rb +4 -4
  84. data/lib/active_support/json/encoding.rb +5 -1
  85. data/lib/active_support/key_generator.rb +1 -1
  86. data/lib/active_support/locale/en.yml +7 -3
  87. data/lib/active_support/log_subscriber.rb +8 -0
  88. data/lib/active_support/logger.rb +1 -1
  89. data/lib/active_support/logger_silence.rb +2 -26
  90. data/lib/active_support/logger_thread_safe_level.rb +34 -12
  91. data/lib/active_support/message_encryptor.rb +4 -7
  92. data/lib/active_support/message_verifier.rb +5 -5
  93. data/lib/active_support/messages/metadata.rb +9 -1
  94. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  95. data/lib/active_support/messages/rotator.rb +6 -5
  96. data/lib/active_support/multibyte/chars.rb +4 -42
  97. data/lib/active_support/multibyte/unicode.rb +9 -83
  98. data/lib/active_support/notifications.rb +32 -5
  99. data/lib/active_support/notifications/fanout.rb +23 -8
  100. data/lib/active_support/notifications/instrumenter.rb +6 -15
  101. data/lib/active_support/number_helper.rb +29 -14
  102. data/lib/active_support/number_helper/number_converter.rb +1 -1
  103. data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -7
  104. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  105. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  106. data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -3
  107. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  108. data/lib/active_support/option_merger.rb +3 -2
  109. data/lib/active_support/ordered_options.rb +8 -2
  110. data/lib/active_support/parameter_filter.rb +16 -11
  111. data/lib/active_support/per_thread_registry.rb +1 -1
  112. data/lib/active_support/rails.rb +1 -4
  113. data/lib/active_support/railtie.rb +23 -1
  114. data/lib/active_support/rescuable.rb +4 -4
  115. data/lib/active_support/secure_compare_rotator.rb +51 -0
  116. data/lib/active_support/security_utils.rb +19 -12
  117. data/lib/active_support/string_inquirer.rb +4 -2
  118. data/lib/active_support/subscriber.rb +12 -7
  119. data/lib/active_support/tagged_logging.rb +29 -4
  120. data/lib/active_support/testing/assertions.rb +18 -11
  121. data/lib/active_support/testing/parallelization.rb +12 -95
  122. data/lib/active_support/testing/parallelization/server.rb +78 -0
  123. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  124. data/lib/active_support/testing/time_helpers.rb +40 -3
  125. data/lib/active_support/time_with_zone.rb +67 -43
  126. data/lib/active_support/values/time_zone.rb +20 -10
  127. data/lib/active_support/xml_mini/rexml.rb +8 -1
  128. metadata +34 -36
  129. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  130. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  131. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  132. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  133. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  134. data/lib/active_support/core_ext/range/include_range.rb +0 -9
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/string_inquirer"
4
+ require "active_support/environment_inquirer"
4
5
 
5
6
  class String
6
7
  # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
@@ -47,9 +47,9 @@ class String
47
47
  # iso_str.is_utf8? # => false
48
48
  def is_utf8?
49
49
  case encoding
50
- when Encoding::UTF_8
50
+ when Encoding::UTF_8, Encoding::US_ASCII
51
51
  valid_encoding?
52
- when Encoding::ASCII_8BIT, Encoding::US_ASCII
52
+ when Encoding::ASCII_8BIT
53
53
  dup.force_encoding(Encoding::UTF_8).valid_encoding?
54
54
  else
55
55
  false
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "erb"
4
- require "active_support/core_ext/kernel/singleton_class"
5
4
  require "active_support/core_ext/module/redefine_method"
6
5
  require "active_support/multibyte/unicode"
7
6
 
@@ -85,7 +84,7 @@ class ERB
85
84
  # use inside HTML attributes.
86
85
  #
87
86
  # If your JSON is being used downstream for insertion into the DOM, be aware of
88
- # whether or not it is being inserted via +html()+. Most jQuery plugins do this.
87
+ # whether or not it is being inserted via <tt>html()</tt>. Most jQuery plugins do this.
89
88
  # If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
90
89
  # content returned by your JSON.
91
90
  #
@@ -135,7 +134,7 @@ module ActiveSupport #:nodoc:
135
134
  class SafeBuffer < String
136
135
  UNSAFE_STRING_METHODS = %w(
137
136
  capitalize chomp chop delete delete_prefix delete_suffix
138
- downcase lstrip next reverse rstrip slice squeeze strip
137
+ downcase lstrip next reverse rstrip scrub slice squeeze strip
139
138
  succ swapcase tr tr_s unicode_normalize upcase
140
139
  )
141
140
 
@@ -153,12 +152,12 @@ module ActiveSupport #:nodoc:
153
152
 
154
153
  def [](*args)
155
154
  if html_safe?
156
- new_safe_buffer = super
155
+ new_string = super
157
156
 
158
- if new_safe_buffer
159
- new_safe_buffer.instance_variable_set :@html_safe, true
160
- end
157
+ return unless new_string
161
158
 
159
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
160
+ new_safe_buffer.instance_variable_set :@html_safe, true
162
161
  new_safe_buffer
163
162
  else
164
163
  to_str[*args]
@@ -202,7 +201,7 @@ module ActiveSupport #:nodoc:
202
201
  end
203
202
 
204
203
  def []=(*args)
205
- if args.count == 3
204
+ if args.length == 3
206
205
  super(args[0], args[1], html_escape_interpolated_argument(args[2]))
207
206
  else
208
207
  super(args[0], html_escape_interpolated_argument(args[1]))
@@ -214,7 +213,8 @@ module ActiveSupport #:nodoc:
214
213
  end
215
214
 
216
215
  def *(*)
217
- new_safe_buffer = super
216
+ new_string = super
217
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
218
218
  new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
219
219
  new_safe_buffer
220
220
  end
@@ -222,7 +222,7 @@ module ActiveSupport #:nodoc:
222
222
  def %(args)
223
223
  case args
224
224
  when Hash
225
- escaped_args = Hash[args.map { |k, arg| [k, html_escape_interpolated_argument(arg)] }]
225
+ escaped_args = args.transform_values { |arg| html_escape_interpolated_argument(arg) }
226
226
  else
227
227
  escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
228
228
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class String
4
- alias_method :starts_with?, :start_with?
5
- alias_method :ends_with?, :end_with?
4
+ alias :starts_with? :start_with?
5
+ alias :ends_with? :end_with?
6
6
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/symbol/starts_ends_with"
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Symbol
4
+ def start_with?(*prefixes)
5
+ to_s.start_with?(*prefixes)
6
+ end unless method_defined?(:start_with?)
7
+
8
+ def end_with?(*suffixes)
9
+ to_s.end_with?(*suffixes)
10
+ end unless method_defined?(:end_with?)
11
+
12
+ alias :starts_with? :start_with?
13
+ alias :ends_with? :end_with?
14
+ end
@@ -6,6 +6,7 @@ require "active_support/time_with_zone"
6
6
  require "active_support/core_ext/time/zones"
7
7
  require "active_support/core_ext/date_and_time/calculations"
8
8
  require "active_support/core_ext/date/calculations"
9
+ require "active_support/core_ext/module/remove_method"
9
10
 
10
11
  class Time
11
12
  include DateAndTime::Calculations
@@ -41,13 +42,21 @@ class Time
41
42
 
42
43
  # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
43
44
  # instances can be used when called with a single argument
44
- def at_with_coercion(*args)
45
- return at_without_coercion(*args) if args.size != 1
45
+ def at_with_coercion(*args, **kwargs)
46
+ if args.size != 1
47
+ if kwargs.empty?
48
+ return at_without_coercion(*args)
49
+ else
50
+ return at_without_coercion(*args, **kwargs)
51
+ end
52
+ end
46
53
 
47
54
  # Time.at can be called with a time or numerical value
48
55
  time_or_number = args.first
49
56
 
50
- if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime)
57
+ if time_or_number.is_a?(ActiveSupport::TimeWithZone)
58
+ at_without_coercion(time_or_number.to_r).getlocal
59
+ elsif time_or_number.is_a?(DateTime)
51
60
  at_without_coercion(time_or_number.to_f).getlocal
52
61
  else
53
62
  at_without_coercion(time_or_number)
@@ -105,6 +114,21 @@ class Time
105
114
  subsec
106
115
  end
107
116
 
117
+ unless Time.method_defined?(:floor)
118
+ def floor(precision = 0)
119
+ change(nsec: 0) + subsec.floor(precision)
120
+ end
121
+ end
122
+
123
+ # Restricted Ruby version due to a bug in `Time#ceil`
124
+ # See https://bugs.ruby-lang.org/issues/17025 for more details
125
+ if RUBY_VERSION <= "2.8"
126
+ remove_possible_method :ceil
127
+ def ceil(precision = 0)
128
+ change(nsec: 0) + subsec.ceil(precision)
129
+ end
130
+ end
131
+
108
132
  # Returns a new Time where one or more of the elements have been changed according
109
133
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
110
134
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "time"
3
4
  require "active_support/inflector/methods"
4
5
  require "active_support/values/time_zone"
5
6
 
6
7
  class Time
7
8
  DATE_FORMATS = {
8
9
  db: "%Y-%m-%d %H:%M:%S",
10
+ inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
9
11
  number: "%Y%m%d%H%M%S",
10
12
  nsec: "%Y%m%d%H%M%S%9N",
11
13
  usec: "%Y%m%d%H%M%S%6N",
@@ -19,7 +19,11 @@ end
19
19
  module URI
20
20
  class << self
21
21
  def parser
22
- @parser ||= URI::Parser.new
22
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
23
+ URI.parser is deprecated and will be removed in Rails 6.2.
24
+ Use `URI::DEFAULT_PARSER` instead.
25
+ MSG
26
+ URI::DEFAULT_PARSER
23
27
  end
24
28
  end
25
29
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/callbacks"
4
+ require "active_support/core_ext/enumerable"
4
5
 
5
6
  module ActiveSupport
6
7
  # Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
@@ -91,7 +92,7 @@ module ActiveSupport
91
92
  class << self
92
93
  # Returns singleton instance for this class in this thread. If none exists, one is created.
93
94
  def instance
94
- current_instances[name] ||= new
95
+ current_instances[current_instances_key] ||= new
95
96
  end
96
97
 
97
98
  # Declares one or more attributes that will be given both class and instance accessor methods.
@@ -150,6 +151,10 @@ module ActiveSupport
150
151
  Thread.current[:current_attributes_instances] ||= {}
151
152
  end
152
153
 
154
+ def current_instances_key
155
+ @current_instances_key ||= name.to_sym
156
+ end
157
+
153
158
  def method_missing(name, *args, &block)
154
159
  # Caches the method definition as a singleton method of the receiver.
155
160
  #
@@ -197,7 +202,7 @@ module ActiveSupport
197
202
  end
198
203
 
199
204
  def compute_attributes(keys)
200
- keys.collect { |key| [ key, public_send(key) ] }.to_h
205
+ keys.index_with { |key| public_send(key) }
201
206
  end
202
207
  end
203
208
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport::CurrentAttributes::TestHelper # :nodoc:
4
+ def before_setup
5
+ ActiveSupport::CurrentAttributes.reset_all
6
+ super
7
+ end
8
+
9
+ def after_teardown
10
+ super
11
+ ActiveSupport::CurrentAttributes.reset_all
12
+ end
13
+ end
@@ -12,7 +12,6 @@ require "active_support/core_ext/object/blank"
12
12
  require "active_support/core_ext/kernel/reporting"
13
13
  require "active_support/core_ext/load_error"
14
14
  require "active_support/core_ext/name_error"
15
- require "active_support/core_ext/string/starts_ends_with"
16
15
  require "active_support/dependencies/interlock"
17
16
  require "active_support/inflector"
18
17
 
@@ -262,15 +261,24 @@ module ActiveSupport #:nodoc:
262
261
 
263
262
  # :doc:
264
263
 
265
- # Interprets a file using <tt>mechanism</tt> and marks its defined
266
- # constants as autoloaded. <tt>file_name</tt> can be either a string or
264
+ # <b>Warning:</b> This method is obsolete in +:zeitwerk+ mode. In
265
+ # +:zeitwerk+ mode semantics match Ruby's and you do not need to be
266
+ # defensive with load order. Just refer to classes and modules normally.
267
+ # If the constant name is dynamic, camelize if needed, and constantize.
268
+ #
269
+ # In +:classic+ mode, interprets a file using +mechanism+ and marks its
270
+ # defined constants as autoloaded. +file_name+ can be either a string or
267
271
  # respond to <tt>to_path</tt>.
268
272
  #
269
- # Use this method in code that absolutely needs a certain constant to be
270
- # defined at that point. A typical use case is to make constant name
271
- # resolution deterministic for constants with the same relative name in
272
- # different namespaces whose evaluation would depend on load order
273
- # otherwise.
273
+ # In +:classic+ mode, use this method in code that absolutely needs a
274
+ # certain constant to be defined at that point. A typical use case is to
275
+ # make constant name resolution deterministic for constants with the same
276
+ # relative name in different namespaces whose evaluation would depend on
277
+ # load order otherwise.
278
+ #
279
+ # Engines that do not control the mode in which their parent application
280
+ # runs should call +require_dependency+ where needed in case the runtime
281
+ # mode is +:classic+.
274
282
  def require_dependency(file_name, message = "No such file to load -- %s.rb")
275
283
  file_name = file_name.to_path if file_name.respond_to?(:to_path)
276
284
  unless file_name.is_a?(String)
@@ -367,7 +375,12 @@ module ActiveSupport #:nodoc:
367
375
  require_or_load(path || file_name)
368
376
  rescue LoadError => load_error
369
377
  if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1]
370
- load_error.message.replace(message % file_name)
378
+ load_error_message = if load_error.respond_to?(:original_message)
379
+ load_error.original_message
380
+ else
381
+ load_error.message
382
+ end
383
+ load_error_message.replace(message % file_name)
371
384
  load_error.copy_blame!(load_error)
372
385
  end
373
386
  raise
@@ -453,7 +466,7 @@ module ActiveSupport #:nodoc:
453
466
 
454
467
  # Search for a file in autoload_paths matching the provided suffix.
455
468
  def search_for_file(path_suffix)
456
- path_suffix += ".rb" unless path_suffix.ends_with?(".rb")
469
+ path_suffix += ".rb" unless path_suffix.end_with?(".rb")
457
470
 
458
471
  autoload_paths.each do |root|
459
472
  path = File.join(root, path_suffix)
@@ -473,9 +486,9 @@ module ActiveSupport #:nodoc:
473
486
  end
474
487
 
475
488
  def load_once_path?(path)
476
- # to_s works around a ruby issue where String#starts_with?(Pathname)
489
+ # to_s works around a ruby issue where String#start_with?(Pathname)
477
490
  # will raise a TypeError: no implicit conversion of Pathname into String
478
- autoload_once_paths.any? { |base| path.starts_with? base.to_s }
491
+ autoload_once_paths.any? { |base| path.start_with?(base.to_s) }
479
492
  end
480
493
 
481
494
  # Attempt to autoload the provided module name by searching for a directory
@@ -525,7 +538,8 @@ module ActiveSupport #:nodoc:
525
538
  # it is not possible to load the constant into from_mod, try its parent
526
539
  # module using +const_missing+.
527
540
  def load_missing_constant(from_mod, const_name)
528
- unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
541
+ from_mod_name = real_mod_name(from_mod)
542
+ unless qualified_const_defined?(from_mod_name) && Inflector.constantize(from_mod_name).equal?(from_mod)
529
543
  raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
530
544
  end
531
545
 
@@ -536,7 +550,7 @@ module ActiveSupport #:nodoc:
536
550
 
537
551
  if file_path
538
552
  expanded = File.expand_path(file_path)
539
- expanded.sub!(/\.rb\z/, "")
553
+ expanded.delete_suffix!(".rb")
540
554
 
541
555
  if loading.include?(expanded)
542
556
  raise "Circular dependency detected while autoloading constant #{qualified_name}"
@@ -584,8 +598,8 @@ module ActiveSupport #:nodoc:
584
598
  end
585
599
  end
586
600
 
587
- name_error = NameError.new("uninitialized constant #{qualified_name}", const_name)
588
- name_error.set_backtrace(caller.reject { |l| l.starts_with? __FILE__ })
601
+ name_error = uninitialized_constant(qualified_name, const_name, receiver: from_mod)
602
+ name_error.set_backtrace(caller.reject { |l| l.start_with? __FILE__ })
589
603
  raise name_error
590
604
  end
591
605
 
@@ -714,7 +728,7 @@ module ActiveSupport #:nodoc:
714
728
  # A module, class, symbol, or string may be provided.
715
729
  def to_constant_name(desc) #:nodoc:
716
730
  case desc
717
- when String then desc.sub(/^::/, "")
731
+ when String then desc.delete_prefix("::")
718
732
  when Symbol then desc.to_s
719
733
  when Module
720
734
  real_mod_name(desc) ||
@@ -725,7 +739,7 @@ module ActiveSupport #:nodoc:
725
739
 
726
740
  def remove_constant(const) #:nodoc:
727
741
  # Normalize ::Foo, ::Object::Foo, Object::Foo, Object::Object::Foo, etc. as Foo.
728
- normalized = const.to_s.sub(/\A::/, "")
742
+ normalized = const.to_s.delete_prefix("::")
729
743
  normalized.sub!(/\A(Object::)+/, "")
730
744
 
731
745
  constants = normalized.split("::")
@@ -735,7 +749,7 @@ module ActiveSupport #:nodoc:
735
749
  file_path = search_for_file(const.underscore)
736
750
  if file_path
737
751
  expanded = File.expand_path(file_path)
738
- expanded.sub!(/\.rb\z/, "")
752
+ expanded.delete_suffix!(".rb")
739
753
  loaded.delete(expanded)
740
754
  end
741
755
 
@@ -793,6 +807,16 @@ module ActiveSupport #:nodoc:
793
807
  end
794
808
 
795
809
  private
810
+ if RUBY_VERSION < "2.6"
811
+ def uninitialized_constant(qualified_name, const_name, receiver:)
812
+ NameError.new("uninitialized constant #{qualified_name}", const_name)
813
+ end
814
+ else
815
+ def uninitialized_constant(qualified_name, const_name, receiver:)
816
+ NameError.new("uninitialized constant #{qualified_name}", const_name, receiver: receiver)
817
+ end
818
+ end
819
+
796
820
  # Returns the original name of a class or module even if `name` has been
797
821
  # overridden.
798
822
  def real_mod_name(mod)
@@ -17,15 +17,18 @@ module ActiveSupport
17
17
  require "active_support/deprecation/instance_delegator"
18
18
  require "active_support/deprecation/behaviors"
19
19
  require "active_support/deprecation/reporting"
20
+ require "active_support/deprecation/disallowed"
20
21
  require "active_support/deprecation/constant_accessor"
21
22
  require "active_support/deprecation/method_wrappers"
22
23
  require "active_support/deprecation/proxy_wrappers"
23
24
  require "active_support/core_ext/module/deprecation"
25
+ require "concurrent/atomic/thread_local_var"
24
26
 
25
27
  include Singleton
26
28
  include InstanceDelegator
27
29
  include Behavior
28
30
  include Reporting
31
+ include Disallowed
29
32
  include MethodWrapper
30
33
 
31
34
  # The version number in which the deprecated behavior will be removed, by default.
@@ -35,12 +38,14 @@ module ActiveSupport
35
38
  # and the second is a library name.
36
39
  #
37
40
  # ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
38
- def initialize(deprecation_horizon = "6.1", gem_name = "Rails")
41
+ def initialize(deprecation_horizon = "6.2", gem_name = "Rails")
39
42
  self.gem_name = gem_name
40
43
  self.deprecation_horizon = deprecation_horizon
41
44
  # By default, warnings are not silenced and debugging is off.
42
45
  self.silenced = false
43
46
  self.debug = false
47
+ @silenced_thread = Concurrent::ThreadLocalVar.new(false)
48
+ @explicitly_allowed_warnings = Concurrent::ThreadLocalVar.new(nil)
44
49
  end
45
50
  end
46
51
  end
@@ -51,7 +51,7 @@ module ActiveSupport
51
51
  # constant. Available behaviors are:
52
52
  #
53
53
  # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
54
- # [+stderr+] Log all deprecation warnings to +$stderr+.
54
+ # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
55
55
  # [+log+] Log all deprecation warnings to +Rails.logger+.
56
56
  # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
57
57
  # [+silence+] Do nothing.
@@ -67,13 +67,18 @@ module ActiveSupport
67
67
  @behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
68
68
  end
69
69
 
70
+ # Returns the current behavior for disallowed deprecations or if one isn't set, defaults to +:raise+.
71
+ def disallowed_behavior
72
+ @disallowed_behavior ||= [DEFAULT_BEHAVIORS[:raise]]
73
+ end
74
+
70
75
  # Sets the behavior to the specified value. Can be a single value, array,
71
76
  # or an object that responds to +call+.
72
77
  #
73
78
  # Available behaviors:
74
79
  #
75
80
  # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
76
- # [+stderr+] Log all deprecation warnings to +$stderr+.
81
+ # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
77
82
  # [+log+] Log all deprecation warnings to +Rails.logger+.
78
83
  # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
79
84
  # [+silence+] Do nothing.
@@ -92,6 +97,14 @@ module ActiveSupport
92
97
  @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
93
98
  end
94
99
 
100
+ # Sets the behavior for disallowed deprecations (those configured by
101
+ # ActiveSupport::Deprecation.disallowed_warnings=) to the specified
102
+ # value. As with +behavior=+, this can be a single value, array, or an
103
+ # object that responds to +call+.
104
+ def disallowed_behavior=(behavior)
105
+ @disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
106
+ end
107
+
95
108
  private
96
109
  def arity_coerce(behavior)
97
110
  unless behavior.respond_to?(:call)