activesupport 5.2.8.1 → 6.0.6

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 (154) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +467 -410
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/backtrace_cleaner.rb +27 -1
  7. data/lib/active_support/cache/file_store.rb +32 -32
  8. data/lib/active_support/cache/mem_cache_store.rb +12 -7
  9. data/lib/active_support/cache/memory_store.rb +15 -9
  10. data/lib/active_support/cache/null_store.rb +8 -3
  11. data/lib/active_support/cache/redis_cache_store.rb +47 -20
  12. data/lib/active_support/cache/strategy/local_cache.rb +22 -22
  13. data/lib/active_support/cache.rb +71 -48
  14. data/lib/active_support/callbacks.rb +16 -8
  15. data/lib/active_support/concern.rb +24 -1
  16. data/lib/active_support/concurrency/share_lock.rb +0 -1
  17. data/lib/active_support/configurable.rb +7 -11
  18. data/lib/active_support/core_ext/array/access.rb +18 -6
  19. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  20. data/lib/active_support/core_ext/array/extract.rb +21 -0
  21. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
  22. data/lib/active_support/core_ext/array.rb +1 -1
  23. data/lib/active_support/core_ext/class/attribute.rb +11 -16
  24. data/lib/active_support/core_ext/class/subclasses.rb +1 -1
  25. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  26. data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -47
  27. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  28. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  29. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  30. data/lib/active_support/core_ext/enumerable.rb +97 -73
  31. data/lib/active_support/core_ext/hash/compact.rb +2 -26
  32. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  33. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  34. data/lib/active_support/core_ext/hash/except.rb +2 -2
  35. data/lib/active_support/core_ext/hash/keys.rb +0 -29
  36. data/lib/active_support/core_ext/hash/slice.rb +3 -25
  37. data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
  38. data/lib/active_support/core_ext/hash.rb +1 -2
  39. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  40. data/lib/active_support/core_ext/kernel.rb +0 -1
  41. data/lib/active_support/core_ext/load_error.rb +1 -1
  42. data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -10
  43. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +13 -19
  44. data/lib/active_support/core_ext/module/delegation.rb +41 -8
  45. data/lib/active_support/core_ext/module/introspection.rb +38 -13
  46. data/lib/active_support/core_ext/module/reachable.rb +1 -6
  47. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  48. data/lib/active_support/core_ext/module.rb +0 -1
  49. data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
  50. data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
  51. data/lib/active_support/core_ext/numeric.rb +0 -1
  52. data/lib/active_support/core_ext/object/blank.rb +1 -2
  53. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  54. data/lib/active_support/core_ext/object/json.rb +2 -1
  55. data/lib/active_support/core_ext/object/try.rb +17 -7
  56. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  57. data/lib/active_support/core_ext/range/compare_range.rb +28 -13
  58. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  59. data/lib/active_support/core_ext/range/each.rb +0 -1
  60. data/lib/active_support/core_ext/range/include_range.rb +6 -0
  61. data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
  62. data/lib/active_support/core_ext/regexp.rb +0 -4
  63. data/lib/active_support/core_ext/securerandom.rb +23 -3
  64. data/lib/active_support/core_ext/string/access.rb +8 -0
  65. data/lib/active_support/core_ext/string/filters.rb +42 -1
  66. data/lib/active_support/core_ext/string/inflections.rb +7 -2
  67. data/lib/active_support/core_ext/string/multibyte.rb +4 -3
  68. data/lib/active_support/core_ext/string/output_safety.rb +68 -10
  69. data/lib/active_support/core_ext/string/strip.rb +3 -1
  70. data/lib/active_support/core_ext/time/calculations.rb +34 -3
  71. data/lib/active_support/core_ext/uri.rb +1 -0
  72. data/lib/active_support/current_attributes.rb +8 -0
  73. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  74. data/lib/active_support/dependencies.rb +74 -18
  75. data/lib/active_support/deprecation/behaviors.rb +1 -1
  76. data/lib/active_support/deprecation/method_wrappers.rb +17 -23
  77. data/lib/active_support/deprecation/proxy_wrappers.rb +28 -5
  78. data/lib/active_support/deprecation.rb +1 -1
  79. data/lib/active_support/descendants_tracker.rb +55 -9
  80. data/lib/active_support/duration/iso8601_parser.rb +2 -4
  81. data/lib/active_support/duration/iso8601_serializer.rb +3 -5
  82. data/lib/active_support/duration.rb +7 -8
  83. data/lib/active_support/encrypted_configuration.rb +0 -4
  84. data/lib/active_support/encrypted_file.rb +3 -2
  85. data/lib/active_support/evented_file_update_checker.rb +39 -10
  86. data/lib/active_support/execution_wrapper.rb +2 -1
  87. data/lib/active_support/file_update_checker.rb +0 -1
  88. data/lib/active_support/gem_version.rb +4 -4
  89. data/lib/active_support/hash_with_indifferent_access.rb +22 -18
  90. data/lib/active_support/i18n.rb +1 -0
  91. data/lib/active_support/i18n_railtie.rb +13 -1
  92. data/lib/active_support/inflector/inflections.rb +1 -5
  93. data/lib/active_support/inflector/methods.rb +16 -29
  94. data/lib/active_support/inflector/transliterate.rb +47 -18
  95. data/lib/active_support/json/decoding.rb +23 -24
  96. data/lib/active_support/json/encoding.rb +6 -2
  97. data/lib/active_support/key_generator.rb +0 -32
  98. data/lib/active_support/lazy_load_hooks.rb +5 -2
  99. data/lib/active_support/locale/en.rb +33 -0
  100. data/lib/active_support/log_subscriber.rb +31 -9
  101. data/lib/active_support/logger.rb +1 -16
  102. data/lib/active_support/logger_silence.rb +28 -12
  103. data/lib/active_support/logger_thread_safe_level.rb +26 -4
  104. data/lib/active_support/message_encryptor.rb +4 -6
  105. data/lib/active_support/message_verifier.rb +5 -5
  106. data/lib/active_support/messages/metadata.rb +11 -2
  107. data/lib/active_support/messages/rotator.rb +4 -4
  108. data/lib/active_support/multibyte/chars.rb +29 -49
  109. data/lib/active_support/multibyte/unicode.rb +44 -282
  110. data/lib/active_support/notifications/fanout.rb +98 -13
  111. data/lib/active_support/notifications/instrumenter.rb +80 -9
  112. data/lib/active_support/notifications.rb +41 -4
  113. data/lib/active_support/number_helper/number_converter.rb +4 -5
  114. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
  115. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
  116. data/lib/active_support/number_helper/number_to_human_converter.rb +3 -2
  117. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -2
  118. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  119. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  120. data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -4
  121. data/lib/active_support/number_helper/rounding_helper.rb +1 -1
  122. data/lib/active_support/number_helper.rb +11 -0
  123. data/lib/active_support/option_merger.rb +21 -3
  124. data/lib/active_support/ordered_hash.rb +1 -1
  125. data/lib/active_support/ordered_options.rb +5 -1
  126. data/lib/active_support/parameter_filter.rb +128 -0
  127. data/lib/active_support/rails.rb +0 -6
  128. data/lib/active_support/reloader.rb +4 -5
  129. data/lib/active_support/security_utils.rb +1 -1
  130. data/lib/active_support/string_inquirer.rb +0 -1
  131. data/lib/active_support/subscriber.rb +65 -26
  132. data/lib/active_support/tagged_logging.rb +13 -4
  133. data/lib/active_support/test_case.rb +91 -0
  134. data/lib/active_support/testing/assertions.rb +15 -1
  135. data/lib/active_support/testing/deprecation.rb +0 -1
  136. data/lib/active_support/testing/file_fixtures.rb +2 -0
  137. data/lib/active_support/testing/isolation.rb +2 -2
  138. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  139. data/lib/active_support/testing/parallelization.rb +134 -0
  140. data/lib/active_support/testing/stream.rb +1 -2
  141. data/lib/active_support/testing/time_helpers.rb +7 -9
  142. data/lib/active_support/time_with_zone.rb +15 -5
  143. data/lib/active_support/values/time_zone.rb +12 -7
  144. data/lib/active_support/xml_mini/jdom.rb +2 -3
  145. data/lib/active_support/xml_mini/libxml.rb +2 -2
  146. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  147. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  148. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  149. data/lib/active_support/xml_mini/rexml.rb +2 -2
  150. data/lib/active_support/xml_mini.rb +2 -10
  151. data/lib/active_support.rb +2 -1
  152. metadata +37 -8
  153. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  154. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -20,6 +20,9 @@ module ActiveSupport #:nodoc:
20
20
  module Dependencies #:nodoc:
21
21
  extend self
22
22
 
23
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
24
+ private_constant :UNBOUND_METHOD_MODULE_NAME
25
+
23
26
  mattr_accessor :interlock, default: Interlock.new
24
27
 
25
28
  # :doc:
@@ -70,6 +73,11 @@ module ActiveSupport #:nodoc:
70
73
  # only once. All directories in this set must also be present in +autoload_paths+.
71
74
  mattr_accessor :autoload_once_paths, default: []
72
75
 
76
+ # This is a private set that collects all eager load paths during bootstrap.
77
+ # Useful for Zeitwerk integration. Its public interface is the config.* path
78
+ # accessors of each engine.
79
+ mattr_accessor :_eager_load_paths, default: Set.new
80
+
73
81
  # An array of qualified constant names that have been loaded. Adding a name
74
82
  # to this array will cause it to be unloaded the next time Dependencies are
75
83
  # cleared.
@@ -79,6 +87,12 @@ module ActiveSupport #:nodoc:
79
87
  # to allow arbitrary constants to be marked for unloading.
80
88
  mattr_accessor :explicitly_unloadable_constants, default: []
81
89
 
90
+ # The logger used when tracing autoloads.
91
+ mattr_accessor :logger
92
+
93
+ # If true, trace autoloads with +logger.debug+.
94
+ mattr_accessor :verbose, default: false
95
+
82
96
  # The WatchStack keeps a stack of the modules being watched as files are
83
97
  # loaded. If a file in the process of being loaded (parent.rb) triggers the
84
98
  # load of another file (child.rb) the stack will ensure that child.rb
@@ -140,7 +154,7 @@ module ActiveSupport #:nodoc:
140
154
 
141
155
  # Normalize the list of new constants, and add them to the list we will return
142
156
  new_constants.each do |suffix|
143
- constants << ([namespace, suffix] - ["Object"]).join("::".freeze)
157
+ constants << ([namespace, suffix] - ["Object"]).join("::")
144
158
  end
145
159
  end
146
160
  constants
@@ -190,6 +204,11 @@ module ActiveSupport #:nodoc:
190
204
  end
191
205
  end
192
206
 
207
+ def self.include_into(base)
208
+ base.include(self)
209
+ append_features(base)
210
+ end
211
+
193
212
  def const_missing(const_name)
194
213
  from_mod = anonymous? ? guess_for_anonymous(const_name) : self
195
214
  Dependencies.load_missing_constant(from_mod, const_name)
@@ -219,6 +238,21 @@ module ActiveSupport #:nodoc:
219
238
  base.class_eval do
220
239
  define_method(:load, Kernel.instance_method(:load))
221
240
  private :load
241
+
242
+ define_method(:require, Kernel.instance_method(:require))
243
+ private :require
244
+ end
245
+ end
246
+
247
+ def self.include_into(base)
248
+ base.include(self)
249
+
250
+ if base.instance_method(:load).owner == base
251
+ base.remove_method(:load)
252
+ end
253
+
254
+ if base.instance_method(:require).owner == base
255
+ base.remove_method(:require)
222
256
  end
223
257
  end
224
258
 
@@ -279,7 +313,6 @@ module ActiveSupport #:nodoc:
279
313
  end
280
314
 
281
315
  private
282
-
283
316
  def load(file, wrap = false)
284
317
  result = false
285
318
  load_dependency(file) { result = super }
@@ -315,9 +348,9 @@ module ActiveSupport #:nodoc:
315
348
  end
316
349
 
317
350
  def hook!
318
- Object.class_eval { include Loadable }
319
- Module.class_eval { include ModuleConstMissing }
320
- Exception.class_eval { include Blamable }
351
+ Loadable.include_into(Object)
352
+ ModuleConstMissing.include_into(Module)
353
+ Exception.include(Blamable)
321
354
  end
322
355
 
323
356
  def unhook!
@@ -334,7 +367,12 @@ module ActiveSupport #:nodoc:
334
367
  require_or_load(path || file_name)
335
368
  rescue LoadError => load_error
336
369
  if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1]
337
- load_error.message.replace(message % file_name)
370
+ load_error_message = if load_error.respond_to?(:original_message)
371
+ load_error.original_message
372
+ else
373
+ load_error.message
374
+ end
375
+ load_error_message.replace(message % file_name)
338
376
  load_error.copy_blame!(load_error)
339
377
  end
340
378
  raise
@@ -349,7 +387,7 @@ module ActiveSupport #:nodoc:
349
387
  end
350
388
 
351
389
  def require_or_load(file_name, const_path = nil)
352
- file_name = $` if file_name =~ /\.rb\z/
390
+ file_name = file_name.chomp(".rb")
353
391
  expanded = File.expand_path(file_name)
354
392
  return if loaded.include?(expanded)
355
393
 
@@ -399,7 +437,7 @@ module ActiveSupport #:nodoc:
399
437
  # constant paths which would cause Dependencies to attempt to load this
400
438
  # file.
401
439
  def loadable_constants_for_path(path, bases = autoload_paths)
402
- path = $` if path =~ /\.rb\z/
440
+ path = path.chomp(".rb")
403
441
  expanded_path = File.expand_path(path)
404
442
  paths = []
405
443
 
@@ -408,7 +446,7 @@ module ActiveSupport #:nodoc:
408
446
  next unless expanded_path.start_with?(expanded_root)
409
447
 
410
448
  root_size = expanded_root.size
411
- next if expanded_path[root_size] != ?/.freeze
449
+ next if expanded_path[root_size] != ?/
412
450
 
413
451
  nesting = expanded_path[(root_size + 1)..-1]
414
452
  paths << nesting.camelize unless nesting.blank?
@@ -420,7 +458,7 @@ module ActiveSupport #:nodoc:
420
458
 
421
459
  # Search for a file in autoload_paths matching the provided suffix.
422
460
  def search_for_file(path_suffix)
423
- path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb".freeze)
461
+ path_suffix += ".rb" unless path_suffix.ends_with?(".rb")
424
462
 
425
463
  autoload_paths.each do |root|
426
464
  path = File.join(root, path_suffix)
@@ -454,6 +492,7 @@ module ActiveSupport #:nodoc:
454
492
  return nil unless base_path = autoloadable_module?(path_suffix)
455
493
  mod = Module.new
456
494
  into.const_set const_name, mod
495
+ log("constant #{qualified_name} autoloaded (module autovivified from #{File.join(base_path, path_suffix)})")
457
496
  autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
458
497
  autoloaded_constants.uniq!
459
498
  mod
@@ -495,26 +534,31 @@ module ActiveSupport #:nodoc:
495
534
  raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
496
535
  end
497
536
 
498
- qualified_name = qualified_name_for from_mod, const_name
537
+ qualified_name = qualified_name_for(from_mod, const_name)
499
538
  path_suffix = qualified_name.underscore
500
539
 
501
540
  file_path = search_for_file(path_suffix)
502
541
 
503
542
  if file_path
504
543
  expanded = File.expand_path(file_path)
505
- expanded.sub!(/\.rb\z/, "".freeze)
544
+ expanded.sub!(/\.rb\z/, "")
506
545
 
507
546
  if loading.include?(expanded)
508
547
  raise "Circular dependency detected while autoloading constant #{qualified_name}"
509
548
  else
510
549
  require_or_load(expanded, qualified_name)
511
- raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)
512
- return from_mod.const_get(const_name)
550
+
551
+ if from_mod.const_defined?(const_name, false)
552
+ log("constant #{qualified_name} autoloaded from #{expanded}.rb")
553
+ return from_mod.const_get(const_name)
554
+ else
555
+ raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it"
556
+ end
513
557
  end
514
558
  elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
515
559
  return mod
516
- elsif (parent = from_mod.parent) && parent != from_mod &&
517
- ! from_mod.parents.any? { |p| p.const_defined?(const_name, false) }
560
+ elsif (parent = from_mod.module_parent) && parent != from_mod &&
561
+ ! from_mod.module_parents.any? { |p| p.const_defined?(const_name, false) }
518
562
  # If our parents do not have a constant named +const_name+ then we are free
519
563
  # to attempt to load upwards. If they do have such a constant, then this
520
564
  # const_missing must be due to from_mod::const_name, which should not
@@ -558,6 +602,7 @@ module ActiveSupport #:nodoc:
558
602
  # as the environment will be in an inconsistent state, e.g. other constants
559
603
  # may have already been unloaded and not accessible.
560
604
  def remove_unloadable_constants!
605
+ log("removing unloadable constants")
561
606
  autoloaded_constants.each { |const| remove_constant const }
562
607
  autoloaded_constants.clear
563
608
  Reference.clear!
@@ -621,7 +666,7 @@ module ActiveSupport #:nodoc:
621
666
 
622
667
  # Determine if the given constant has been automatically loaded.
623
668
  def autoloaded?(desc)
624
- return false if desc.is_a?(Module) && desc.anonymous?
669
+ return false if desc.is_a?(Module) && real_mod_name(desc).nil?
625
670
  name = to_constant_name desc
626
671
  return false unless qualified_const_defined?(name)
627
672
  autoloaded_constants.include?(name)
@@ -677,7 +722,7 @@ module ActiveSupport #:nodoc:
677
722
  when String then desc.sub(/^::/, "")
678
723
  when Symbol then desc.to_s
679
724
  when Module
680
- desc.name ||
725
+ real_mod_name(desc) ||
681
726
  raise(ArgumentError, "Anonymous modules have no name to be referenced by")
682
727
  else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
683
728
  end
@@ -747,6 +792,17 @@ module ActiveSupport #:nodoc:
747
792
  # The constant is no longer reachable, just skip it.
748
793
  end
749
794
  end
795
+
796
+ def log(message)
797
+ logger.debug("autoloading: #{message}") if logger && verbose
798
+ end
799
+
800
+ private
801
+ # Returns the original name of a class or module even if `name` has been
802
+ # overridden.
803
+ def real_mod_name(mod)
804
+ UNBOUND_METHOD_MODULE_NAME.bind(mod).call
805
+ end
750
806
  end
751
807
  end
752
808
 
@@ -43,7 +43,7 @@ module ActiveSupport
43
43
  deprecation_horizon: deprecation_horizon)
44
44
  },
45
45
 
46
- silence: ->(message, callstack, deprecation_horizon, gem_name) {},
46
+ silence: ->(message, callstack, deprecation_horizon, gem_name) { },
47
47
  }
48
48
 
49
49
  # Behavior module allows to determine how to display deprecation messages.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/module/aliasing"
4
3
  require "active_support/core_ext/array/extract_options"
4
+ require "active_support/core_ext/module/redefine_method"
5
5
 
6
6
  module ActiveSupport
7
7
  class Deprecation
@@ -53,37 +53,31 @@ module ActiveSupport
53
53
  options = method_names.extract_options!
54
54
  deprecator = options.delete(:deprecator) || self
55
55
  method_names += options.keys
56
- mod = Module.new
56
+ mod = nil
57
57
 
58
58
  method_names.each do |method_name|
59
59
  if target_module.method_defined?(method_name) || target_module.private_method_defined?(method_name)
60
- aliased_method, punctuation = method_name.to_s.sub(/([?!=])$/, ""), $1
61
- with_method = "#{aliased_method}_with_deprecation#{punctuation}"
62
- without_method = "#{aliased_method}_without_deprecation#{punctuation}"
63
-
64
- target_module.send(:define_method, with_method) do |*args, &block|
65
- deprecator.deprecation_warning(method_name, options[method_name])
66
- send(without_method, *args, &block)
67
- end
68
-
69
- target_module.send(:alias_method, without_method, method_name)
70
- target_module.send(:alias_method, method_name, with_method)
71
-
72
- case
73
- when target_module.protected_method_defined?(without_method)
74
- target_module.send(:protected, method_name)
75
- when target_module.private_method_defined?(without_method)
76
- target_module.send(:private, method_name)
60
+ method = target_module.instance_method(method_name)
61
+ target_module.module_eval do
62
+ redefine_method(method_name) do |*args, &block|
63
+ deprecator.deprecation_warning(method_name, options[method_name])
64
+ method.bind(self).call(*args, &block)
65
+ end
66
+ ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
77
67
  end
78
68
  else
79
- mod.send(:define_method, method_name) do |*args, &block|
80
- deprecator.deprecation_warning(method_name, options[method_name])
81
- super(*args, &block)
69
+ mod ||= Module.new
70
+ mod.module_eval do
71
+ define_method(method_name) do |*args, &block|
72
+ deprecator.deprecation_warning(method_name, options[method_name])
73
+ super(*args, &block)
74
+ end
75
+ ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
82
76
  end
83
77
  end
84
78
  end
85
79
 
86
- target_module.prepend(mod) unless mod.instance_methods(false).empty?
80
+ target_module.prepend(mod) if mod
87
81
  end
88
82
  end
89
83
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/regexp"
4
-
5
3
  module ActiveSupport
6
4
  class Deprecation
7
5
  class DeprecationProxy #:nodoc:
@@ -122,7 +120,14 @@ module ActiveSupport
122
120
  # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
123
121
  # (Backtrace information…)
124
122
  # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
125
- class DeprecatedConstantProxy < DeprecationProxy
123
+ class DeprecatedConstantProxy < Module
124
+ def self.new(*args, **kwargs, &block)
125
+ object = args.first
126
+
127
+ return object unless object
128
+ super
129
+ end
130
+
126
131
  def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
127
132
  require "active_support/inflector/methods"
128
133
 
@@ -132,6 +137,18 @@ module ActiveSupport
132
137
  @message = message
133
138
  end
134
139
 
140
+ instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
141
+
142
+ # Don't give a deprecation warning on inspect since test/unit and error
143
+ # logs rely on it for diagnostics.
144
+ def inspect
145
+ target.inspect
146
+ end
147
+
148
+ # Don't give a deprecation warning on methods that IRB may invoke
149
+ # during tab-completion.
150
+ delegate :hash, :instance_methods, :name, :respond_to?, to: :target
151
+
135
152
  # Returns the class of the new constant.
136
153
  #
137
154
  # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
@@ -146,8 +163,14 @@ module ActiveSupport
146
163
  ActiveSupport::Inflector.constantize(@new_const.to_s)
147
164
  end
148
165
 
149
- def warn(callstack, called, args)
150
- @deprecator.warn(@message, callstack)
166
+ def const_missing(name)
167
+ @deprecator.warn(@message, caller_locations)
168
+ target.const_get(name)
169
+ end
170
+
171
+ def method_missing(called, *args, &block)
172
+ @deprecator.warn(@message, caller_locations)
173
+ target.__send__(called, *args, &block)
151
174
  end
152
175
  end
153
176
  end
@@ -35,7 +35,7 @@ module ActiveSupport
35
35
  # and the second is a library name.
36
36
  #
37
37
  # ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
38
- def initialize(deprecation_horizon = "6.0", gem_name = "Rails")
38
+ def initialize(deprecation_horizon = "6.1", gem_name = "Rails")
39
39
  self.gem_name = gem_name
40
40
  self.deprecation_horizon = deprecation_horizon
41
41
  # By default, warnings are not silenced and debugging is off.
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "weakref"
4
+
3
5
  module ActiveSupport
4
6
  # This module provides an internal implementation to track descendants
5
7
  # which is faster than iterating through ObjectSpace.
@@ -8,7 +10,8 @@ module ActiveSupport
8
10
 
9
11
  class << self
10
12
  def direct_descendants(klass)
11
- @@direct_descendants[klass] || []
13
+ descendants = @@direct_descendants[klass]
14
+ descendants ? descendants.to_a : []
12
15
  end
13
16
 
14
17
  def descendants(klass)
@@ -20,10 +23,10 @@ module ActiveSupport
20
23
  def clear
21
24
  if defined? ActiveSupport::Dependencies
22
25
  @@direct_descendants.each do |klass, descendants|
23
- if ActiveSupport::Dependencies.autoloaded?(klass)
26
+ if Dependencies.autoloaded?(klass)
24
27
  @@direct_descendants.delete(klass)
25
28
  else
26
- descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) }
29
+ descendants.reject! { |v| Dependencies.autoloaded?(v) }
27
30
  end
28
31
  end
29
32
  else
@@ -34,16 +37,18 @@ module ActiveSupport
34
37
  # This is the only method that is not thread safe, but is only ever called
35
38
  # during the eager loading phase.
36
39
  def store_inherited(klass, descendant)
37
- (@@direct_descendants[klass] ||= []) << descendant
40
+ (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
38
41
  end
39
42
 
40
43
  private
41
- def accumulate_descendants(klass, acc)
42
- if direct_descendants = @@direct_descendants[klass]
43
- acc.concat(direct_descendants)
44
- direct_descendants.each { |direct_descendant| accumulate_descendants(direct_descendant, acc) }
44
+ def accumulate_descendants(klass, acc)
45
+ if direct_descendants = @@direct_descendants[klass]
46
+ direct_descendants.each do |direct_descendant|
47
+ acc << direct_descendant
48
+ accumulate_descendants(direct_descendant, acc)
49
+ end
50
+ end
45
51
  end
46
- end
47
52
  end
48
53
 
49
54
  def inherited(base)
@@ -58,5 +63,46 @@ module ActiveSupport
58
63
  def descendants
59
64
  DescendantsTracker.descendants(self)
60
65
  end
66
+
67
+ # DescendantsArray is an array that contains weak references to classes.
68
+ class DescendantsArray # :nodoc:
69
+ include Enumerable
70
+
71
+ def initialize
72
+ @refs = []
73
+ end
74
+
75
+ def initialize_copy(orig)
76
+ @refs = @refs.dup
77
+ end
78
+
79
+ def <<(klass)
80
+ cleanup!
81
+ @refs << WeakRef.new(klass)
82
+ end
83
+
84
+ def each
85
+ @refs.each do |ref|
86
+ yield ref.__getobj__
87
+ rescue WeakRef::RefError
88
+ end
89
+ end
90
+
91
+ def refs_size
92
+ @refs.size
93
+ end
94
+
95
+ def cleanup!
96
+ @refs.delete_if { |ref| !ref.weakref_alive? }
97
+ end
98
+
99
+ def reject!
100
+ @refs.reject! do |ref|
101
+ yield ref.__getobj__
102
+ rescue WeakRef::RefError
103
+ true
104
+ end
105
+ end
106
+ end
61
107
  end
62
108
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "strscan"
4
- require "active_support/core_ext/regexp"
5
4
 
6
5
  module ActiveSupport
7
6
  class Duration
@@ -14,8 +13,8 @@ module ActiveSupport
14
13
  class ParsingError < ::ArgumentError; end
15
14
 
16
15
  PERIOD_OR_COMMA = /\.|,/
17
- PERIOD = ".".freeze
18
- COMMA = ",".freeze
16
+ PERIOD = "."
17
+ COMMA = ","
19
18
 
20
19
  SIGN_MARKER = /\A\-|\+|/
21
20
  DATE_MARKER = /P/
@@ -81,7 +80,6 @@ module ActiveSupport
81
80
  end
82
81
 
83
82
  private
84
-
85
83
  def finished?
86
84
  scanner.eos?
87
85
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/blank"
4
- require "active_support/core_ext/hash/transform_values"
5
4
 
6
5
  module ActiveSupport
7
6
  class Duration
@@ -15,14 +14,14 @@ module ActiveSupport
15
14
  # Builds and returns output string.
16
15
  def serialize
17
16
  parts, sign = normalize
18
- return "PT0S".freeze if parts.empty?
17
+ return "PT0S" if parts.empty?
19
18
 
20
- output = "P".dup
19
+ output = +"P"
21
20
  output << "#{parts[:years]}Y" if parts.key?(:years)
22
21
  output << "#{parts[:months]}M" if parts.key?(:months)
23
22
  output << "#{parts[:weeks]}W" if parts.key?(:weeks)
24
23
  output << "#{parts[:days]}D" if parts.key?(:days)
25
- time = "".dup
24
+ time = +""
26
25
  time << "#{parts[:hours]}H" if parts.key?(:hours)
27
26
  time << "#{parts[:minutes]}M" if parts.key?(:minutes)
28
27
  if parts.key?(:seconds)
@@ -33,7 +32,6 @@ module ActiveSupport
33
32
  end
34
33
 
35
34
  private
36
-
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.
@@ -4,7 +4,6 @@ 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
6
  require "active_support/core_ext/string/filters"
7
- require "active_support/deprecation"
8
7
 
9
8
  module ActiveSupport
10
9
  # Provides accurate date and time measurements using Date#advance and
@@ -199,7 +198,6 @@ module ActiveSupport
199
198
  end
200
199
 
201
200
  private
202
-
203
201
  def calculate_total_seconds(parts)
204
202
  parts.inject(0) do |total, (part, value)|
205
203
  total + value * PARTS_IN_SECONDS[part]
@@ -214,8 +212,11 @@ module ActiveSupport
214
212
  end
215
213
 
216
214
  def coerce(other) #:nodoc:
217
- if Scalar === other
215
+ case other
216
+ when Scalar
218
217
  [other, self]
218
+ when Duration
219
+ [Scalar.new(other.value), self]
219
220
  else
220
221
  [Scalar.new(other), self]
221
222
  end
@@ -336,8 +337,8 @@ module ActiveSupport
336
337
  # 1.year.to_i # => 31556952
337
338
  #
338
339
  # In such cases, Ruby's core
339
- # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
340
- # Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
340
+ # Date[https://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
341
+ # Time[https://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
341
342
  # date and time arithmetic.
342
343
  def to_i
343
344
  @value.to_i
@@ -370,10 +371,9 @@ module ActiveSupport
370
371
  alias :before :ago
371
372
 
372
373
  def inspect #:nodoc:
373
- return "0 seconds" if parts.empty?
374
+ return "#{value} seconds" if parts.empty?
374
375
 
375
376
  parts.
376
- reduce(::Hash.new(0)) { |h, (l, r)| h[l] += r; h }.
377
377
  sort_by { |unit, _ | PARTS.index(unit) }.
378
378
  map { |unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}" }.
379
379
  to_sentence(locale: ::I18n.default_locale)
@@ -398,7 +398,6 @@ module ActiveSupport
398
398
  end
399
399
 
400
400
  private
401
-
402
401
  def sum(sign, time = ::Time.current)
403
402
  unless time.acts_like?(:time) || time.acts_like?(:date)
404
403
  raise ::ArgumentError, "expected a time or date, got #{time.inspect}"
@@ -38,10 +38,6 @@ module ActiveSupport
38
38
  @options ||= ActiveSupport::InheritableOptions.new(config)
39
39
  end
40
40
 
41
- def serialize(config)
42
- config.present? ? YAML.dump(config) : ""
43
- end
44
-
45
41
  def deserialize(config)
46
42
  YAML.load(config).presence || {}
47
43
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require "tmpdir"
4
5
  require "active_support/message_encryptor"
5
6
 
6
7
  module ActiveSupport
@@ -67,7 +68,7 @@ module ActiveSupport
67
68
 
68
69
  write(updated_contents) if updated_contents != contents
69
70
  ensure
70
- FileUtils.rm(tmp_path) if tmp_path.exist?
71
+ FileUtils.rm(tmp_path) if tmp_path&.exist?
71
72
  end
72
73
 
73
74
 
@@ -93,7 +94,7 @@ module ActiveSupport
93
94
  end
94
95
 
95
96
  def handle_missing_key
96
- raise MissingKeyError, key_path: key_path, env_key: env_key if raise_if_missing_key
97
+ raise MissingKeyError.new(key_path: key_path, env_key: env_key) if raise_if_missing_key
97
98
  end
98
99
  end
99
100
  end