activesupport 6.0.0.beta1 → 6.0.1.rc1
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.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +302 -1
- data/README.rdoc +2 -1
- data/lib/active_support.rb +1 -0
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +5 -1
- data/lib/active_support/cache.rb +5 -5
- data/lib/active_support/cache/file_store.rb +3 -10
- data/lib/active_support/cache/memory_store.rb +4 -2
- data/lib/active_support/cache/redis_cache_store.rb +9 -6
- data/lib/active_support/concern.rb +24 -1
- data/lib/active_support/configurable.rb +3 -3
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/class/attribute.rb +10 -15
- data/lib/active_support/core_ext/date_and_time/calculations.rb +0 -30
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +24 -4
- data/lib/active_support/core_ext/hash.rb +1 -0
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +5 -5
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +5 -5
- data/lib/active_support/core_ext/module/delegation.rb +6 -0
- data/lib/active_support/core_ext/object/duplicable.rb +7 -117
- data/lib/active_support/core_ext/range/compare_range.rb +27 -12
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +7 -2
- data/lib/active_support/core_ext/string/output_safety.rb +51 -4
- data/lib/active_support/core_ext/time/calculations.rb +31 -2
- data/lib/active_support/current_attributes.rb +6 -0
- data/lib/active_support/dependencies.rb +41 -5
- data/lib/active_support/dependencies/zeitwerk_integration.rb +118 -0
- data/lib/active_support/deprecation/method_wrappers.rb +7 -18
- data/lib/active_support/deprecation/proxy_wrappers.rb +24 -3
- data/lib/active_support/descendants_tracker.rb +52 -6
- data/lib/active_support/duration.rb +2 -3
- data/lib/active_support/encrypted_file.rb +2 -1
- data/lib/active_support/evented_file_update_checker.rb +14 -2
- data/lib/active_support/gem_version.rb +2 -2
- data/lib/active_support/hash_with_indifferent_access.rb +19 -3
- data/lib/active_support/i18n_railtie.rb +2 -1
- data/lib/active_support/inflector/transliterate.rb +43 -14
- data/lib/active_support/logger_thread_safe_level.rb +2 -1
- data/lib/active_support/message_encryptor.rb +1 -1
- data/lib/active_support/message_verifier.rb +1 -1
- data/lib/active_support/notifications.rb +9 -0
- data/lib/active_support/notifications/fanout.rb +60 -13
- data/lib/active_support/notifications/instrumenter.rb +11 -10
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +1 -1
- data/lib/active_support/parameter_filter.rb +6 -1
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/subscriber.rb +55 -6
- data/lib/active_support/testing/parallelization.rb +21 -2
- metadata +27 -7
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
@@ -119,10 +119,16 @@ module ActiveSupport
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
# Calls this block before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
|
123
|
+
def before_reset(&block)
|
124
|
+
set_callback :reset, :before, &block
|
125
|
+
end
|
126
|
+
|
122
127
|
# Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
|
123
128
|
def resets(&block)
|
124
129
|
set_callback :reset, :after, &block
|
125
130
|
end
|
131
|
+
alias_method :after_reset, :resets
|
126
132
|
|
127
133
|
delegate :set, :reset, to: :instance
|
128
134
|
|
@@ -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.
|
@@ -196,6 +204,11 @@ module ActiveSupport #:nodoc:
|
|
196
204
|
end
|
197
205
|
end
|
198
206
|
|
207
|
+
def self.include_into(base)
|
208
|
+
base.include(self)
|
209
|
+
append_features(base)
|
210
|
+
end
|
211
|
+
|
199
212
|
def const_missing(const_name)
|
200
213
|
from_mod = anonymous? ? guess_for_anonymous(const_name) : self
|
201
214
|
Dependencies.load_missing_constant(from_mod, const_name)
|
@@ -225,6 +238,21 @@ module ActiveSupport #:nodoc:
|
|
225
238
|
base.class_eval do
|
226
239
|
define_method(:load, Kernel.instance_method(:load))
|
227
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)
|
228
256
|
end
|
229
257
|
end
|
230
258
|
|
@@ -321,9 +349,9 @@ module ActiveSupport #:nodoc:
|
|
321
349
|
end
|
322
350
|
|
323
351
|
def hook!
|
324
|
-
Object
|
325
|
-
Module
|
326
|
-
Exception.
|
352
|
+
Loadable.include_into(Object)
|
353
|
+
ModuleConstMissing.include_into(Module)
|
354
|
+
Exception.include(Blamable)
|
327
355
|
end
|
328
356
|
|
329
357
|
def unhook!
|
@@ -634,7 +662,7 @@ module ActiveSupport #:nodoc:
|
|
634
662
|
|
635
663
|
# Determine if the given constant has been automatically loaded.
|
636
664
|
def autoloaded?(desc)
|
637
|
-
return false if desc.is_a?(Module) && desc.
|
665
|
+
return false if desc.is_a?(Module) && real_mod_name(desc).nil?
|
638
666
|
name = to_constant_name desc
|
639
667
|
return false unless qualified_const_defined?(name)
|
640
668
|
autoloaded_constants.include?(name)
|
@@ -690,7 +718,7 @@ module ActiveSupport #:nodoc:
|
|
690
718
|
when String then desc.sub(/^::/, "")
|
691
719
|
when Symbol then desc.to_s
|
692
720
|
when Module
|
693
|
-
desc
|
721
|
+
real_mod_name(desc) ||
|
694
722
|
raise(ArgumentError, "Anonymous modules have no name to be referenced by")
|
695
723
|
else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
|
696
724
|
end
|
@@ -764,6 +792,14 @@ module ActiveSupport #:nodoc:
|
|
764
792
|
def log(message)
|
765
793
|
logger.debug("autoloading: #{message}") if logger && verbose
|
766
794
|
end
|
795
|
+
|
796
|
+
private
|
797
|
+
|
798
|
+
# Returns the original name of a class or module even if `name` has been
|
799
|
+
# overridden.
|
800
|
+
def real_mod_name(mod)
|
801
|
+
UNBOUND_METHOD_MODULE_NAME.bind(mod).call
|
802
|
+
end
|
767
803
|
end
|
768
804
|
end
|
769
805
|
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
require "active_support/core_ext/string/inflections"
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
module Dependencies
|
8
|
+
module ZeitwerkIntegration # :nodoc: all
|
9
|
+
module Decorations
|
10
|
+
def clear
|
11
|
+
Dependencies.unload_interlock do
|
12
|
+
Rails.autoloaders.main.reload
|
13
|
+
rescue Zeitwerk::ReloadingDisabledError
|
14
|
+
raise "reloading is disabled because config.cache_classes is true"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def constantize(cpath)
|
19
|
+
ActiveSupport::Inflector.constantize(cpath)
|
20
|
+
end
|
21
|
+
|
22
|
+
def safe_constantize(cpath)
|
23
|
+
ActiveSupport::Inflector.safe_constantize(cpath)
|
24
|
+
end
|
25
|
+
|
26
|
+
def autoloaded_constants
|
27
|
+
Rails.autoloaders.main.unloadable_cpaths
|
28
|
+
end
|
29
|
+
|
30
|
+
def autoloaded?(object)
|
31
|
+
cpath = object.is_a?(Module) ? real_mod_name(object) : object.to_s
|
32
|
+
Rails.autoloaders.main.unloadable_cpath?(cpath)
|
33
|
+
end
|
34
|
+
|
35
|
+
def verbose=(verbose)
|
36
|
+
l = verbose ? logger || Rails.logger : nil
|
37
|
+
Rails.autoloaders.each { |autoloader| autoloader.logger = l }
|
38
|
+
end
|
39
|
+
|
40
|
+
def unhook!
|
41
|
+
:no_op
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module RequireDependency
|
46
|
+
def require_dependency(filename)
|
47
|
+
filename = filename.to_path if filename.respond_to?(:to_path)
|
48
|
+
if abspath = ActiveSupport::Dependencies.search_for_file(filename)
|
49
|
+
require abspath
|
50
|
+
else
|
51
|
+
require filename
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
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
|
+
|
61
|
+
def self.camelize(basename, _abspath)
|
62
|
+
@overrides[basename] || basename.camelize
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.inflect(overrides)
|
66
|
+
@overrides.merge!(overrides)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class << self
|
71
|
+
def take_over(enable_reloading:)
|
72
|
+
setup_autoloaders(enable_reloading)
|
73
|
+
freeze_paths
|
74
|
+
decorate_dependencies
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def setup_autoloaders(enable_reloading)
|
80
|
+
Dependencies.autoload_paths.each do |autoload_path|
|
81
|
+
# Zeitwerk only accepts existing directories in `push_dir` to
|
82
|
+
# prevent misconfigurations.
|
83
|
+
next unless File.directory?(autoload_path)
|
84
|
+
|
85
|
+
autoloader = \
|
86
|
+
autoload_once?(autoload_path) ? Rails.autoloaders.once : Rails.autoloaders.main
|
87
|
+
|
88
|
+
autoloader.push_dir(autoload_path)
|
89
|
+
autoloader.do_not_eager_load(autoload_path) unless eager_load?(autoload_path)
|
90
|
+
end
|
91
|
+
|
92
|
+
Rails.autoloaders.main.enable_reloading if enable_reloading
|
93
|
+
Rails.autoloaders.each(&:setup)
|
94
|
+
end
|
95
|
+
|
96
|
+
def autoload_once?(autoload_path)
|
97
|
+
Dependencies.autoload_once_paths.include?(autoload_path)
|
98
|
+
end
|
99
|
+
|
100
|
+
def eager_load?(autoload_path)
|
101
|
+
Dependencies._eager_load_paths.member?(autoload_path)
|
102
|
+
end
|
103
|
+
|
104
|
+
def freeze_paths
|
105
|
+
Dependencies.autoload_paths.freeze
|
106
|
+
Dependencies.autoload_once_paths.freeze
|
107
|
+
Dependencies._eager_load_paths.freeze
|
108
|
+
end
|
109
|
+
|
110
|
+
def decorate_dependencies
|
111
|
+
Dependencies.unhook!
|
112
|
+
Dependencies.singleton_class.prepend(Decorations)
|
113
|
+
Object.prepend(RequireDependency)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/array/extract_options"
|
4
|
+
require "active_support/core_ext/module/redefine_method"
|
4
5
|
|
5
6
|
module ActiveSupport
|
6
7
|
class Deprecation
|
@@ -52,29 +53,17 @@ module ActiveSupport
|
|
52
53
|
options = method_names.extract_options!
|
53
54
|
deprecator = options.delete(:deprecator) || self
|
54
55
|
method_names += options.keys
|
55
|
-
mod =
|
56
|
+
mod = nil
|
56
57
|
|
57
58
|
method_names.each do |method_name|
|
58
59
|
if target_module.method_defined?(method_name) || target_module.private_method_defined?(method_name)
|
59
|
-
|
60
|
-
|
61
|
-
without_method = "#{aliased_method}_without_deprecation#{punctuation}"
|
62
|
-
|
63
|
-
target_module.define_method(with_method) do |*args, &block|
|
60
|
+
method = target_module.instance_method(method_name)
|
61
|
+
target_module.redefine_method(method_name) do |*args, &block|
|
64
62
|
deprecator.deprecation_warning(method_name, options[method_name])
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
target_module.alias_method(without_method, method_name)
|
69
|
-
target_module.alias_method(method_name, with_method)
|
70
|
-
|
71
|
-
case
|
72
|
-
when target_module.protected_method_defined?(without_method)
|
73
|
-
target_module.send(:protected, method_name)
|
74
|
-
when target_module.private_method_defined?(without_method)
|
75
|
-
target_module.send(:private, method_name)
|
63
|
+
method.bind(self).call(*args, &block)
|
76
64
|
end
|
77
65
|
else
|
66
|
+
mod ||= Module.new
|
78
67
|
mod.define_method(method_name) do |*args, &block|
|
79
68
|
deprecator.deprecation_warning(method_name, options[method_name])
|
80
69
|
super(*args, &block)
|
@@ -82,7 +71,7 @@ module ActiveSupport
|
|
82
71
|
end
|
83
72
|
end
|
84
73
|
|
85
|
-
target_module.prepend(mod)
|
74
|
+
target_module.prepend(mod) if mod
|
86
75
|
end
|
87
76
|
end
|
88
77
|
end
|
@@ -120,7 +120,14 @@ module ActiveSupport
|
|
120
120
|
# # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
|
121
121
|
# (Backtrace information…)
|
122
122
|
# ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
|
123
|
-
class DeprecatedConstantProxy <
|
123
|
+
class DeprecatedConstantProxy < Module
|
124
|
+
def self.new(*args, &block)
|
125
|
+
object = args.first
|
126
|
+
|
127
|
+
return object unless object
|
128
|
+
super
|
129
|
+
end
|
130
|
+
|
124
131
|
def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
|
125
132
|
require "active_support/inflector/methods"
|
126
133
|
|
@@ -130,6 +137,14 @@ module ActiveSupport
|
|
130
137
|
@message = message
|
131
138
|
end
|
132
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
|
+
|
133
148
|
# Returns the class of the new constant.
|
134
149
|
#
|
135
150
|
# PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
|
@@ -144,8 +159,14 @@ module ActiveSupport
|
|
144
159
|
ActiveSupport::Inflector.constantize(@new_const.to_s)
|
145
160
|
end
|
146
161
|
|
147
|
-
def
|
148
|
-
@deprecator.warn(@message,
|
162
|
+
def const_missing(name)
|
163
|
+
@deprecator.warn(@message, caller_locations)
|
164
|
+
target.const_get(name)
|
165
|
+
end
|
166
|
+
|
167
|
+
def method_missing(called, *args, &block)
|
168
|
+
@deprecator.warn(@message, caller_locations)
|
169
|
+
target.__send__(called, *args, &block)
|
149
170
|
end
|
150
171
|
end
|
151
172
|
end
|
@@ -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
|
26
|
+
if Dependencies.autoloaded?(klass)
|
24
27
|
@@direct_descendants.delete(klass)
|
25
28
|
else
|
26
|
-
descendants.reject! { |v|
|
29
|
+
descendants.reject! { |v| Dependencies.autoloaded?(v) }
|
27
30
|
end
|
28
31
|
end
|
29
32
|
else
|
@@ -34,15 +37,17 @@ 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] ||=
|
40
|
+
(@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
|
38
41
|
end
|
39
42
|
|
40
43
|
private
|
41
44
|
|
42
45
|
def accumulate_descendants(klass, acc)
|
43
46
|
if direct_descendants = @@direct_descendants[klass]
|
44
|
-
|
45
|
-
|
47
|
+
direct_descendants.each do |direct_descendant|
|
48
|
+
acc << direct_descendant
|
49
|
+
accumulate_descendants(direct_descendant, acc)
|
50
|
+
end
|
46
51
|
end
|
47
52
|
end
|
48
53
|
end
|
@@ -59,5 +64,46 @@ module ActiveSupport
|
|
59
64
|
def descendants
|
60
65
|
DescendantsTracker.descendants(self)
|
61
66
|
end
|
67
|
+
|
68
|
+
# DescendantsArray is an array that contains weak references to classes.
|
69
|
+
class DescendantsArray # :nodoc:
|
70
|
+
include Enumerable
|
71
|
+
|
72
|
+
def initialize
|
73
|
+
@refs = []
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize_copy(orig)
|
77
|
+
@refs = @refs.dup
|
78
|
+
end
|
79
|
+
|
80
|
+
def <<(klass)
|
81
|
+
cleanup!
|
82
|
+
@refs << WeakRef.new(klass)
|
83
|
+
end
|
84
|
+
|
85
|
+
def each
|
86
|
+
@refs.each do |ref|
|
87
|
+
yield ref.__getobj__
|
88
|
+
rescue WeakRef::RefError
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def refs_size
|
93
|
+
@refs.size
|
94
|
+
end
|
95
|
+
|
96
|
+
def cleanup!
|
97
|
+
@refs.delete_if { |ref| !ref.weakref_alive? }
|
98
|
+
end
|
99
|
+
|
100
|
+
def reject!
|
101
|
+
@refs.reject! do |ref|
|
102
|
+
yield ref.__getobj__
|
103
|
+
rescue WeakRef::RefError
|
104
|
+
true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
62
108
|
end
|
63
109
|
end
|
@@ -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
|
@@ -339,8 +338,8 @@ module ActiveSupport
|
|
339
338
|
# 1.year.to_i # => 31556952
|
340
339
|
#
|
341
340
|
# In such cases, Ruby's core
|
342
|
-
# Date[
|
343
|
-
# Time[
|
341
|
+
# Date[https://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
|
342
|
+
# Time[https://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
|
344
343
|
# date and time arithmetic.
|
345
344
|
def to_i
|
346
345
|
@value.to_i
|