activesupport 6.0.0 → 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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +381 -349
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  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 -4
  8. data/lib/active_support/benchmarkable.rb +1 -1
  9. data/lib/active_support/cache.rb +101 -59
  10. data/lib/active_support/cache/file_store.rb +11 -11
  11. data/lib/active_support/cache/mem_cache_store.rb +34 -33
  12. data/lib/active_support/cache/memory_store.rb +52 -31
  13. data/lib/active_support/cache/null_store.rb +3 -3
  14. data/lib/active_support/cache/redis_cache_store.rb +38 -33
  15. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  16. data/lib/active_support/callbacks.rb +65 -59
  17. data/lib/active_support/concern.rb +46 -2
  18. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  19. data/lib/active_support/concurrency/share_lock.rb +0 -1
  20. data/lib/active_support/configurable.rb +3 -3
  21. data/lib/active_support/configuration_file.rb +46 -0
  22. data/lib/active_support/core_ext.rb +1 -1
  23. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  24. data/lib/active_support/core_ext/benchmark.rb +2 -2
  25. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  26. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  27. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  28. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  29. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  30. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  31. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  32. data/lib/active_support/core_ext/enumerable.rb +76 -4
  33. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  34. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  35. data/lib/active_support/core_ext/hash/except.rb +1 -1
  36. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  37. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  38. data/lib/active_support/core_ext/load_error.rb +1 -1
  39. data/lib/active_support/core_ext/marshal.rb +2 -0
  40. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  41. data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
  42. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
  43. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  44. data/lib/active_support/core_ext/module/delegation.rb +46 -29
  45. data/lib/active_support/core_ext/module/introspection.rb +2 -25
  46. data/lib/active_support/core_ext/name_error.rb +29 -2
  47. data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
  48. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  49. data/lib/active_support/core_ext/object/json.rb +13 -2
  50. data/lib/active_support/core_ext/object/try.rb +4 -2
  51. data/lib/active_support/core_ext/range/compare_range.rb +15 -3
  52. data/lib/active_support/core_ext/range/each.rb +0 -1
  53. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  54. data/lib/active_support/core_ext/regexp.rb +8 -1
  55. data/lib/active_support/core_ext/string/access.rb +5 -24
  56. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  57. data/lib/active_support/core_ext/string/inflections.rb +38 -4
  58. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  59. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  60. data/lib/active_support/core_ext/string/output_safety.rb +12 -11
  61. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  62. data/lib/active_support/core_ext/symbol.rb +3 -0
  63. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  64. data/lib/active_support/core_ext/time/calculations.rb +27 -3
  65. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  66. data/lib/active_support/core_ext/uri.rb +5 -1
  67. data/lib/active_support/current_attributes.rb +7 -2
  68. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  69. data/lib/active_support/dependencies.rb +42 -20
  70. data/lib/active_support/dependencies/zeitwerk_integration.rb +9 -2
  71. data/lib/active_support/deprecation.rb +6 -1
  72. data/lib/active_support/deprecation/behaviors.rb +15 -2
  73. data/lib/active_support/deprecation/disallowed.rb +56 -0
  74. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  75. data/lib/active_support/deprecation/method_wrappers.rb +13 -6
  76. data/lib/active_support/deprecation/proxy_wrappers.rb +6 -2
  77. data/lib/active_support/deprecation/reporting.rb +50 -7
  78. data/lib/active_support/descendants_tracker.rb +6 -3
  79. data/lib/active_support/duration.rb +86 -35
  80. data/lib/active_support/duration/iso8601_parser.rb +0 -1
  81. data/lib/active_support/duration/iso8601_serializer.rb +15 -10
  82. data/lib/active_support/encrypted_file.rb +20 -3
  83. data/lib/active_support/environment_inquirer.rb +20 -0
  84. data/lib/active_support/evented_file_update_checker.rb +69 -134
  85. data/lib/active_support/file_update_checker.rb +0 -1
  86. data/lib/active_support/fork_tracker.rb +62 -0
  87. data/lib/active_support/gem_version.rb +2 -2
  88. data/lib/active_support/hash_with_indifferent_access.rb +43 -24
  89. data/lib/active_support/i18n_railtie.rb +15 -16
  90. data/lib/active_support/inflector/inflections.rb +1 -3
  91. data/lib/active_support/inflector/methods.rb +36 -33
  92. data/lib/active_support/inflector/transliterate.rb +4 -4
  93. data/lib/active_support/json/decoding.rb +4 -5
  94. data/lib/active_support/json/encoding.rb +5 -1
  95. data/lib/active_support/key_generator.rb +1 -1
  96. data/lib/active_support/lazy_load_hooks.rb +0 -1
  97. data/lib/active_support/locale/en.rb +4 -2
  98. data/lib/active_support/locale/en.yml +7 -3
  99. data/lib/active_support/log_subscriber.rb +8 -1
  100. data/lib/active_support/logger.rb +2 -2
  101. data/lib/active_support/logger_silence.rb +2 -26
  102. data/lib/active_support/logger_thread_safe_level.rb +34 -12
  103. data/lib/active_support/message_encryptor.rb +5 -8
  104. data/lib/active_support/message_verifier.rb +7 -7
  105. data/lib/active_support/messages/metadata.rb +11 -2
  106. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  107. data/lib/active_support/messages/rotator.rb +10 -9
  108. data/lib/active_support/multibyte/chars.rb +5 -44
  109. data/lib/active_support/multibyte/unicode.rb +9 -84
  110. data/lib/active_support/notifications.rb +32 -5
  111. data/lib/active_support/notifications/fanout.rb +23 -8
  112. data/lib/active_support/notifications/instrumenter.rb +7 -16
  113. data/lib/active_support/number_helper.rb +33 -14
  114. data/lib/active_support/number_helper/number_converter.rb +5 -6
  115. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -7
  116. data/lib/active_support/number_helper/number_to_delimited_converter.rb +0 -1
  117. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -2
  118. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -2
  119. data/lib/active_support/number_helper/number_to_phone_converter.rb +0 -1
  120. data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -4
  121. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  122. data/lib/active_support/option_merger.rb +22 -3
  123. data/lib/active_support/ordered_hash.rb +1 -1
  124. data/lib/active_support/ordered_options.rb +13 -3
  125. data/lib/active_support/parameter_filter.rb +17 -13
  126. data/lib/active_support/per_thread_registry.rb +1 -1
  127. data/lib/active_support/rails.rb +1 -4
  128. data/lib/active_support/railtie.rb +23 -1
  129. data/lib/active_support/rescuable.rb +4 -4
  130. data/lib/active_support/secure_compare_rotator.rb +51 -0
  131. data/lib/active_support/security_utils.rb +19 -12
  132. data/lib/active_support/string_inquirer.rb +4 -3
  133. data/lib/active_support/subscriber.rb +12 -7
  134. data/lib/active_support/tagged_logging.rb +29 -4
  135. data/lib/active_support/testing/assertions.rb +18 -11
  136. data/lib/active_support/testing/parallelization.rb +12 -89
  137. data/lib/active_support/testing/parallelization/server.rb +78 -0
  138. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  139. data/lib/active_support/testing/stream.rb +0 -1
  140. data/lib/active_support/testing/time_helpers.rb +40 -5
  141. data/lib/active_support/time_with_zone.rb +67 -43
  142. data/lib/active_support/values/time_zone.rb +20 -10
  143. data/lib/active_support/xml_mini.rb +0 -1
  144. data/lib/active_support/xml_mini/jdom.rb +0 -1
  145. data/lib/active_support/xml_mini/rexml.rb +8 -1
  146. metadata +39 -38
  147. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  148. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  149. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  150. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  151. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  152. 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
@@ -291,13 +291,14 @@ module ActiveSupport #:nodoc:
291
291
  end
292
292
 
293
293
  private
294
-
295
294
  def html_escape_interpolated_argument(arg)
296
295
  (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
297
296
  end
298
297
 
299
298
  def set_block_back_references(block, match_data)
300
299
  block.binding.eval("proc { |m| $~ = m }").call(match_data)
300
+ rescue ArgumentError
301
+ # Can't create binding from C level Proc
301
302
  end
302
303
  end
303
304
  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)
@@ -313,7 +321,6 @@ module ActiveSupport #:nodoc:
313
321
  end
314
322
 
315
323
  private
316
-
317
324
  def load(file, wrap = false)
318
325
  result = false
319
326
  load_dependency(file) { result = super }
@@ -368,7 +375,12 @@ module ActiveSupport #:nodoc:
368
375
  require_or_load(path || file_name)
369
376
  rescue LoadError => load_error
370
377
  if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1]
371
- 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)
372
384
  load_error.copy_blame!(load_error)
373
385
  end
374
386
  raise
@@ -454,7 +466,7 @@ module ActiveSupport #:nodoc:
454
466
 
455
467
  # Search for a file in autoload_paths matching the provided suffix.
456
468
  def search_for_file(path_suffix)
457
- path_suffix += ".rb" unless path_suffix.ends_with?(".rb")
469
+ path_suffix += ".rb" unless path_suffix.end_with?(".rb")
458
470
 
459
471
  autoload_paths.each do |root|
460
472
  path = File.join(root, path_suffix)
@@ -474,9 +486,9 @@ module ActiveSupport #:nodoc:
474
486
  end
475
487
 
476
488
  def load_once_path?(path)
477
- # 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)
478
490
  # will raise a TypeError: no implicit conversion of Pathname into String
479
- autoload_once_paths.any? { |base| path.starts_with? base.to_s }
491
+ autoload_once_paths.any? { |base| path.start_with?(base.to_s) }
480
492
  end
481
493
 
482
494
  # Attempt to autoload the provided module name by searching for a directory
@@ -526,7 +538,8 @@ module ActiveSupport #:nodoc:
526
538
  # it is not possible to load the constant into from_mod, try its parent
527
539
  # module using +const_missing+.
528
540
  def load_missing_constant(from_mod, const_name)
529
- 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)
530
543
  raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
531
544
  end
532
545
 
@@ -537,7 +550,7 @@ module ActiveSupport #:nodoc:
537
550
 
538
551
  if file_path
539
552
  expanded = File.expand_path(file_path)
540
- expanded.sub!(/\.rb\z/, "")
553
+ expanded.delete_suffix!(".rb")
541
554
 
542
555
  if loading.include?(expanded)
543
556
  raise "Circular dependency detected while autoloading constant #{qualified_name}"
@@ -585,8 +598,8 @@ module ActiveSupport #:nodoc:
585
598
  end
586
599
  end
587
600
 
588
- name_error = NameError.new("uninitialized constant #{qualified_name}", const_name)
589
- 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__ })
590
603
  raise name_error
591
604
  end
592
605
 
@@ -715,7 +728,7 @@ module ActiveSupport #:nodoc:
715
728
  # A module, class, symbol, or string may be provided.
716
729
  def to_constant_name(desc) #:nodoc:
717
730
  case desc
718
- when String then desc.sub(/^::/, "")
731
+ when String then desc.delete_prefix("::")
719
732
  when Symbol then desc.to_s
720
733
  when Module
721
734
  real_mod_name(desc) ||
@@ -726,7 +739,7 @@ module ActiveSupport #:nodoc:
726
739
 
727
740
  def remove_constant(const) #:nodoc:
728
741
  # Normalize ::Foo, ::Object::Foo, Object::Foo, Object::Object::Foo, etc. as Foo.
729
- normalized = const.to_s.sub(/\A::/, "")
742
+ normalized = const.to_s.delete_prefix("::")
730
743
  normalized.sub!(/\A(Object::)+/, "")
731
744
 
732
745
  constants = normalized.split("::")
@@ -736,7 +749,7 @@ module ActiveSupport #:nodoc:
736
749
  file_path = search_for_file(const.underscore)
737
750
  if file_path
738
751
  expanded = File.expand_path(file_path)
739
- expanded.sub!(/\.rb\z/, "")
752
+ expanded.delete_suffix!(".rb")
740
753
  loaded.delete(expanded)
741
754
  end
742
755
 
@@ -794,6 +807,15 @@ module ActiveSupport #:nodoc:
794
807
  end
795
808
 
796
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
797
819
 
798
820
  # Returns the original name of a class or module even if `name` has been
799
821
  # overridden.
@@ -54,8 +54,16 @@ module ActiveSupport
54
54
  end
55
55
 
56
56
  module Inflector
57
+ # Concurrent::Map is not needed. This is a private class, and overrides
58
+ # must be defined while the application boots.
59
+ @overrides = {}
60
+
57
61
  def self.camelize(basename, _abspath)
58
- basename.camelize
62
+ @overrides[basename] || basename.camelize
63
+ end
64
+
65
+ def self.inflect(overrides)
66
+ @overrides.merge!(overrides)
59
67
  end
60
68
  end
61
69
 
@@ -67,7 +75,6 @@ module ActiveSupport
67
75
  end
68
76
 
69
77
  private
70
-
71
78
  def setup_autoloaders(enable_reloading)
72
79
  Dependencies.autoload_paths.each do |autoload_path|
73
80
  # Zeitwerk only accepts existing directories in `push_dir` to