activesupport 6.1.7.2 → 7.0.7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +286 -491
- data/README.rdoc +2 -2
- data/lib/active_support/actionable_error.rb +1 -1
- data/lib/active_support/array_inquirer.rb +0 -2
- data/lib/active_support/backtrace_cleaner.rb +2 -2
- data/lib/active_support/benchmarkable.rb +2 -2
- data/lib/active_support/cache/file_store.rb +15 -9
- data/lib/active_support/cache/mem_cache_store.rb +148 -37
- data/lib/active_support/cache/memory_store.rb +24 -16
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +59 -78
- data/lib/active_support/cache/strategy/local_cache.rb +38 -61
- data/lib/active_support/cache.rb +299 -147
- data/lib/active_support/callbacks.rb +184 -85
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +5 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/configuration_file.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +13 -12
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +25 -17
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +24 -9
- data/lib/active_support/core_ext/date/conversions.rb +14 -14
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +37 -0
- data/lib/active_support/core_ext/date.rb +1 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +4 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +33 -0
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +39 -14
- data/lib/active_support/core_ext/enumerable.rb +112 -38
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +0 -1
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +19 -10
- data/lib/active_support/core_ext/module/delegation.rb +2 -8
- data/lib/active_support/core_ext/name_error.rb +2 -8
- data/lib/active_support/core_ext/numeric/conversions.rb +80 -77
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +15 -4
- data/lib/active_support/core_ext/object/json.rb +30 -25
- data/lib/active_support/core_ext/object/to_query.rb +2 -4
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with_options.rb +21 -2
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +0 -25
- data/lib/active_support/core_ext/range/conversions.rb +8 -8
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +33 -0
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +3 -26
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +1 -1
- data/lib/active_support/core_ext/securerandom.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +1 -5
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +66 -38
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/time/calculations.rb +11 -8
- data/lib/active_support/core_ext/time/conversions.rb +13 -12
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +33 -0
- data/lib/active_support/core_ext/time/zones.rb +10 -26
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +3 -27
- data/lib/active_support/core_ext.rb +1 -0
- data/lib/active_support/current_attributes.rb +31 -15
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -788
- data/lib/active_support/deprecation/behaviors.rb +8 -5
- data/lib/active_support/deprecation/disallowed.rb +3 -3
- data/lib/active_support/deprecation/method_wrappers.rb +3 -3
- data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
- data/lib/active_support/deprecation.rb +2 -2
- data/lib/active_support/descendants_tracker.rb +174 -68
- data/lib/active_support/digest.rb +4 -4
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +9 -1
- data/lib/active_support/duration.rb +77 -48
- data/lib/active_support/encrypted_configuration.rb +45 -3
- data/lib/active_support/encrypted_file.rb +13 -1
- data/lib/active_support/environment_inquirer.rb +1 -1
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +20 -7
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +30 -11
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/fork_tracker.rb +19 -12
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +3 -1
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +1 -1
- data/lib/active_support/inflector/inflections.rb +23 -7
- data/lib/active_support/inflector/methods.rb +28 -53
- data/lib/active_support/inflector/transliterate.rb +1 -1
- data/lib/active_support/isolated_execution_state.rb +72 -0
- data/lib/active_support/json/encoding.rb +3 -3
- data/lib/active_support/key_generator.rb +22 -5
- data/lib/active_support/lazy_load_hooks.rb +28 -4
- data/lib/active_support/locale/en.yml +1 -1
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +15 -5
- data/lib/active_support/logger_thread_safe_level.rb +4 -13
- data/lib/active_support/message_encryptor.rb +12 -6
- data/lib/active_support/message_verifier.rb +46 -14
- data/lib/active_support/messages/metadata.rb +2 -2
- data/lib/active_support/multibyte/chars.rb +10 -11
- data/lib/active_support/multibyte/unicode.rb +0 -12
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +91 -65
- data/lib/active_support/notifications/instrumenter.rb +32 -15
- data/lib/active_support/notifications.rb +23 -23
- data/lib/active_support/number_helper/number_converter.rb +1 -3
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
- data/lib/active_support/number_helper/rounding_helper.rb +1 -5
- data/lib/active_support/number_helper.rb +4 -5
- data/lib/active_support/option_merger.rb +10 -18
- 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 +20 -11
- data/lib/active_support/per_thread_registry.rb +5 -1
- data/lib/active_support/railtie.rb +69 -19
- data/lib/active_support/rescuable.rb +12 -12
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +2 -2
- data/lib/active_support/string_inquirer.rb +0 -2
- data/lib/active_support/subscriber.rb +7 -18
- data/lib/active_support/tagged_logging.rb +1 -1
- data/lib/active_support/test_case.rb +13 -21
- data/lib/active_support/testing/assertions.rb +35 -5
- data/lib/active_support/testing/deprecation.rb +52 -1
- data/lib/active_support/testing/isolation.rb +30 -29
- data/lib/active_support/testing/method_call_assertions.rb +5 -5
- data/lib/active_support/testing/parallelization/server.rb +4 -0
- data/lib/active_support/testing/parallelization/worker.rb +3 -0
- data/lib/active_support/testing/parallelization.rb +4 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/stream.rb +3 -5
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +13 -2
- data/lib/active_support/time_with_zone.rb +69 -22
- data/lib/active_support/values/time_zone.rb +33 -14
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +4 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +5 -4
- data/lib/active_support.rb +16 -0
- metadata +25 -23
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
@@ -3,27 +3,36 @@
|
|
3
3
|
require "active_support/core_ext/object/duplicable"
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
|
-
# +ParameterFilter+
|
7
|
-
#
|
8
|
-
# sub-keys from a hash is possible by using the dot notation:
|
9
|
-
# 'credit_card.number'. If a proc is given, each key and value of a hash and
|
10
|
-
# all sub-hashes are passed to it, where the value or the key can be replaced
|
11
|
-
# using String#replace or similar methods.
|
6
|
+
# +ParameterFilter+ replaces values in a <tt>Hash</tt>-like object if their
|
7
|
+
# keys match one of the specified filters.
|
12
8
|
#
|
9
|
+
# Matching based on nested keys is possible by using dot notation, e.g.
|
10
|
+
# <tt>"credit_card.number"</tt>.
|
11
|
+
#
|
12
|
+
# If a proc is given as a filter, each key and value of the <tt>Hash</tt>-like
|
13
|
+
# and of any nested <tt>Hash</tt>es will be passed to it. The value or key can
|
14
|
+
# then be mutated as desired using methods such as <tt>String#replace</tt>.
|
15
|
+
#
|
16
|
+
# # Replaces values with "[FILTERED]" for keys that match /password/i.
|
13
17
|
# ActiveSupport::ParameterFilter.new([:password])
|
14
|
-
# => replaces the value to all keys matching /password/i with "[FILTERED]"
|
15
18
|
#
|
19
|
+
# # Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
|
16
20
|
# ActiveSupport::ParameterFilter.new([:foo, "bar"])
|
17
|
-
# => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
18
21
|
#
|
22
|
+
# # Replaces values for the exact key "pin" and for keys that begin with
|
23
|
+
# # "pin_". Does not match keys that otherwise include "pin" as a
|
24
|
+
# # substring, such as "shipping_id".
|
25
|
+
# ActiveSupport::ParameterFilter.new([/\Apin\z/, /\Apin_/])
|
26
|
+
#
|
27
|
+
# # Replaces the value for :code in `{ credit_card: { code: "xxxx" } }`.
|
28
|
+
# # Does not change `{ file: { code: "xxxx" } }`.
|
19
29
|
# ActiveSupport::ParameterFilter.new(["credit_card.code"])
|
20
|
-
# => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
|
21
|
-
# change { file: { code: "xxxx"} }
|
22
30
|
#
|
31
|
+
# # Reverses values for keys that match /secret/i.
|
23
32
|
# ActiveSupport::ParameterFilter.new([-> (k, v) do
|
24
33
|
# v.reverse! if /secret/i.match?(k)
|
25
34
|
# end])
|
26
|
-
#
|
35
|
+
#
|
27
36
|
class ParameterFilter
|
28
37
|
FILTERED = "[FILTERED]" # :nodoc:
|
29
38
|
|
@@ -40,6 +40,10 @@ module ActiveSupport
|
|
40
40
|
# If the class has an initializer, it must accept no arguments.
|
41
41
|
module PerThreadRegistry
|
42
42
|
def self.extended(object)
|
43
|
+
ActiveSupport::Deprecation.warn(<<~MSG)
|
44
|
+
ActiveSupport::PerThreadRegistry is deprecated and will be removed in Rails 7.1.
|
45
|
+
Use `Module#thread_mattr_accessor` instead.
|
46
|
+
MSG
|
43
47
|
object.instance_variable_set :@per_thread_registry_key, object.name.freeze
|
44
48
|
end
|
45
49
|
|
@@ -56,6 +60,6 @@ module ActiveSupport
|
|
56
60
|
|
57
61
|
send(name, *args, &block)
|
58
62
|
end
|
59
|
-
ruby2_keywords(:method_missing)
|
63
|
+
ruby2_keywords(:method_missing)
|
60
64
|
end
|
61
65
|
end
|
@@ -6,9 +6,27 @@ require "active_support/i18n_railtie"
|
|
6
6
|
module ActiveSupport
|
7
7
|
class Railtie < Rails::Railtie # :nodoc:
|
8
8
|
config.active_support = ActiveSupport::OrderedOptions.new
|
9
|
+
config.active_support.disable_to_s_conversion = false
|
9
10
|
|
10
11
|
config.eager_load_namespaces << ActiveSupport
|
11
12
|
|
13
|
+
initializer "active_support.isolation_level" do |app|
|
14
|
+
config.after_initialize do
|
15
|
+
if level = app.config.active_support.delete(:isolation_level)
|
16
|
+
ActiveSupport::IsolatedExecutionState.isolation_level = level
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
initializer "active_support.remove_deprecated_time_with_zone_name" do |app|
|
22
|
+
config.after_initialize do
|
23
|
+
if app.config.active_support.remove_deprecated_time_with_zone_name
|
24
|
+
require "active_support/time_with_zone"
|
25
|
+
TimeWithZone.singleton_class.remove_method(:name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
12
30
|
initializer "active_support.set_authenticated_message_encryption" do |app|
|
13
31
|
config.after_initialize do
|
14
32
|
unless app.config.active_support.use_authenticated_message_encryption.nil?
|
@@ -18,28 +36,48 @@ module ActiveSupport
|
|
18
36
|
end
|
19
37
|
end
|
20
38
|
|
39
|
+
initializer "active_support.reset_execution_context" do |app|
|
40
|
+
app.reloader.before_class_unload { ActiveSupport::ExecutionContext.clear }
|
41
|
+
app.executor.to_run { ActiveSupport::ExecutionContext.clear }
|
42
|
+
app.executor.to_complete { ActiveSupport::ExecutionContext.clear }
|
43
|
+
end
|
44
|
+
|
21
45
|
initializer "active_support.reset_all_current_attributes_instances" do |app|
|
22
46
|
app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
|
23
47
|
app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
|
24
48
|
app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
|
25
49
|
|
26
50
|
ActiveSupport.on_load(:active_support_test_case) do
|
27
|
-
|
28
|
-
|
51
|
+
if app.config.active_support.executor_around_test_case
|
52
|
+
require "active_support/executor/test_helper"
|
53
|
+
include ActiveSupport::Executor::TestHelper
|
54
|
+
else
|
55
|
+
require "active_support/current_attributes/test_helper"
|
56
|
+
include ActiveSupport::CurrentAttributes::TestHelper
|
57
|
+
|
58
|
+
require "active_support/execution_context/test_helper"
|
59
|
+
include ActiveSupport::ExecutionContext::TestHelper
|
60
|
+
end
|
29
61
|
end
|
30
62
|
end
|
31
63
|
|
32
64
|
initializer "active_support.deprecation_behavior" do |app|
|
33
|
-
if
|
34
|
-
ActiveSupport::Deprecation.
|
35
|
-
|
65
|
+
if app.config.active_support.report_deprecations == false
|
66
|
+
ActiveSupport::Deprecation.silenced = true
|
67
|
+
ActiveSupport::Deprecation.behavior = :silence
|
68
|
+
ActiveSupport::Deprecation.disallowed_behavior = :silence
|
69
|
+
else
|
70
|
+
if deprecation = app.config.active_support.deprecation
|
71
|
+
ActiveSupport::Deprecation.behavior = deprecation
|
72
|
+
end
|
36
73
|
|
37
|
-
|
38
|
-
|
39
|
-
|
74
|
+
if disallowed_deprecation = app.config.active_support.disallowed_deprecation
|
75
|
+
ActiveSupport::Deprecation.disallowed_behavior = disallowed_deprecation
|
76
|
+
end
|
40
77
|
|
41
|
-
|
42
|
-
|
78
|
+
if disallowed_warnings = app.config.active_support.disallowed_deprecation_warnings
|
79
|
+
ActiveSupport::Deprecation.disallowed_warnings = disallowed_warnings
|
80
|
+
end
|
43
81
|
end
|
44
82
|
end
|
45
83
|
|
@@ -75,6 +113,10 @@ module ActiveSupport
|
|
75
113
|
end
|
76
114
|
end
|
77
115
|
|
116
|
+
initializer "active_support.set_error_reporter" do |app|
|
117
|
+
ActiveSupport.error_reporter = app.executor.error_reporter
|
118
|
+
end
|
119
|
+
|
78
120
|
initializer "active_support.set_configs" do |app|
|
79
121
|
app.config.active_support.each do |k, v|
|
80
122
|
k = "#{k}="
|
@@ -84,19 +126,27 @@ module ActiveSupport
|
|
84
126
|
|
85
127
|
initializer "active_support.set_hash_digest_class" do |app|
|
86
128
|
config.after_initialize do
|
87
|
-
if app.config.active_support.use_sha1_digests
|
88
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
89
|
-
config.active_support.use_sha1_digests is deprecated and will
|
90
|
-
be removed from Rails 7.0. Use
|
91
|
-
config.active_support.hash_digest_class = ::Digest::SHA1 instead.
|
92
|
-
MSG
|
93
|
-
ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
|
94
|
-
end
|
95
|
-
|
96
129
|
if klass = app.config.active_support.hash_digest_class
|
97
130
|
ActiveSupport::Digest.hash_digest_class = klass
|
98
131
|
end
|
99
132
|
end
|
100
133
|
end
|
134
|
+
|
135
|
+
initializer "active_support.set_key_generator_hash_digest_class" do |app|
|
136
|
+
config.after_initialize do
|
137
|
+
if klass = app.config.active_support.key_generator_hash_digest_class
|
138
|
+
ActiveSupport::KeyGenerator.hash_digest_class = klass
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
initializer "active_support.set_rfc4122_namespaced_uuids" do |app|
|
144
|
+
config.after_initialize do
|
145
|
+
if app.config.active_support.use_rfc4122_namespaced_uuids
|
146
|
+
require "active_support/core_ext/digest"
|
147
|
+
::Digest::UUID.use_rfc4122_namespaced_uuids = app.config.active_support.use_rfc4122_namespaced_uuids
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
101
151
|
end
|
102
152
|
end
|
@@ -30,20 +30,20 @@ module ActiveSupport
|
|
30
30
|
# any.
|
31
31
|
#
|
32
32
|
# class ApplicationController < ActionController::Base
|
33
|
-
# rescue_from User::NotAuthorized, with: :deny_access
|
34
|
-
# rescue_from ActiveRecord::RecordInvalid, with: :
|
33
|
+
# rescue_from User::NotAuthorized, with: :deny_access
|
34
|
+
# rescue_from ActiveRecord::RecordInvalid, with: :show_record_errors
|
35
35
|
#
|
36
|
-
# rescue_from
|
37
|
-
#
|
36
|
+
# rescue_from "MyApp::BaseError" do |exception|
|
37
|
+
# redirect_to root_url, alert: exception.message
|
38
38
|
# end
|
39
39
|
#
|
40
40
|
# private
|
41
41
|
# def deny_access
|
42
|
-
#
|
42
|
+
# head :forbidden
|
43
43
|
# end
|
44
44
|
#
|
45
|
-
# def
|
46
|
-
# exception.record.
|
45
|
+
# def show_record_errors(exception)
|
46
|
+
# redirect_back_or_to root_url, alert: exception.record.errors.full_messages.to_sentence
|
47
47
|
# end
|
48
48
|
# end
|
49
49
|
#
|
@@ -74,12 +74,12 @@ module ActiveSupport
|
|
74
74
|
# Matches an exception to a handler based on the exception class.
|
75
75
|
#
|
76
76
|
# If no handler matches the exception, check for a handler matching the
|
77
|
-
# (optional) exception.cause
|
77
|
+
# (optional) +exception.cause+. If no handler matches the exception or its
|
78
78
|
# cause, this returns +nil+, so you can deal with unhandled exceptions.
|
79
79
|
# Be sure to re-raise unhandled exceptions if this is what you expect.
|
80
80
|
#
|
81
81
|
# begin
|
82
|
-
#
|
82
|
+
# # ...
|
83
83
|
# rescue => exception
|
84
84
|
# rescue_with_handler(exception) || raise
|
85
85
|
# end
|
@@ -100,7 +100,7 @@ module ActiveSupport
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
-
def handler_for_rescue(exception, object: self)
|
103
|
+
def handler_for_rescue(exception, object: self) # :nodoc:
|
104
104
|
case rescuer = find_rescue_handler(exception)
|
105
105
|
when Symbol
|
106
106
|
method = object.method(rescuer)
|
@@ -160,14 +160,14 @@ module ActiveSupport
|
|
160
160
|
end
|
161
161
|
|
162
162
|
# Delegates to the class method, but uses the instance as the subject for
|
163
|
-
# rescue_from handlers (method calls, instance_exec blocks).
|
163
|
+
# rescue_from handlers (method calls, +instance_exec+ blocks).
|
164
164
|
def rescue_with_handler(exception)
|
165
165
|
self.class.rescue_with_handler exception, object: self
|
166
166
|
end
|
167
167
|
|
168
168
|
# Internal handler lookup. Delegates to class method. Some libraries call
|
169
169
|
# this directly, so keeping it around for compatibility.
|
170
|
-
def handler_for_rescue(exception)
|
170
|
+
def handler_for_rescue(exception) # :nodoc:
|
171
171
|
self.class.handler_for_rescue exception, object: self
|
172
172
|
end
|
173
173
|
end
|
@@ -4,7 +4,7 @@ require "active_support/security_utils"
|
|
4
4
|
require "active_support/messages/rotator"
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
|
-
# The ActiveSupport::SecureCompareRotator is a wrapper around
|
7
|
+
# The ActiveSupport::SecureCompareRotator is a wrapper around ActiveSupport::SecurityUtils.secure_compare
|
8
8
|
# and allows you to rotate a previously defined value to a new one.
|
9
9
|
#
|
10
10
|
# It can be used as follow:
|
@@ -17,7 +17,7 @@ module ActiveSupport
|
|
17
17
|
#
|
18
18
|
# class MyController < ApplicationController
|
19
19
|
# def authenticate_request
|
20
|
-
# rotator = ActiveSupport::
|
20
|
+
# rotator = ActiveSupport::SecureCompareRotator.new('new_password')
|
21
21
|
# rotator.rotate('old_password')
|
22
22
|
#
|
23
23
|
# authenticate_or_request_with_http_basic do |username, password|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/per_thread_registry"
|
4
3
|
require "active_support/notifications"
|
5
4
|
|
6
5
|
module ActiveSupport
|
@@ -150,25 +149,15 @@ module ActiveSupport
|
|
150
149
|
send(method, event)
|
151
150
|
end
|
152
151
|
|
152
|
+
def publish_event(event) # :nodoc:
|
153
|
+
method = event.name.split(".").first
|
154
|
+
send(method, event)
|
155
|
+
end
|
156
|
+
|
153
157
|
private
|
154
158
|
def event_stack
|
155
|
-
|
159
|
+
registry = ActiveSupport::IsolatedExecutionState[:active_support_subscriber_queue_registry] ||= {}
|
160
|
+
registry[@queue_key] ||= []
|
156
161
|
end
|
157
162
|
end
|
158
|
-
|
159
|
-
# This is a registry for all the event stacks kept for subscribers.
|
160
|
-
#
|
161
|
-
# See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
|
162
|
-
# for further details.
|
163
|
-
class SubscriberQueueRegistry # :nodoc:
|
164
|
-
extend PerThreadRegistry
|
165
|
-
|
166
|
-
def initialize
|
167
|
-
@registry = {}
|
168
|
-
end
|
169
|
-
|
170
|
-
def get_queue(queue_key)
|
171
|
-
@registry[queue_key] ||= []
|
172
|
-
end
|
173
|
-
end
|
174
163
|
end
|
@@ -57,7 +57,7 @@ module ActiveSupport
|
|
57
57
|
def current_tags
|
58
58
|
# We use our object ID here to avoid conflicting with other instances
|
59
59
|
thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
|
60
|
-
|
60
|
+
IsolatedExecutionState[thread_key] ||= []
|
61
61
|
end
|
62
62
|
|
63
63
|
def tags_text
|
@@ -12,6 +12,7 @@ require "active_support/testing/constant_lookup"
|
|
12
12
|
require "active_support/testing/time_helpers"
|
13
13
|
require "active_support/testing/file_fixtures"
|
14
14
|
require "active_support/testing/parallelization"
|
15
|
+
require "active_support/testing/parallelize_executor"
|
15
16
|
require "concurrent/utility/processor_counter"
|
16
17
|
|
17
18
|
module ActiveSupport
|
@@ -71,26 +72,17 @@ module ActiveSupport
|
|
71
72
|
#
|
72
73
|
# The threaded parallelization uses minitest's parallel executor directly.
|
73
74
|
# The processes parallelization uses a Ruby DRb server.
|
74
|
-
|
75
|
+
#
|
76
|
+
# Because parallelization presents an overhead, it is only enabled when the
|
77
|
+
# number of tests to run is above the +threshold+ param. The default value is
|
78
|
+
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
79
|
+
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
|
75
80
|
workers = Concurrent.physical_processor_count if workers == :number_of_processors
|
76
81
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
77
82
|
|
78
83
|
return if workers <= 1
|
79
84
|
|
80
|
-
|
81
|
-
when :processes
|
82
|
-
Testing::Parallelization.new(workers)
|
83
|
-
when :threads
|
84
|
-
Minitest::Parallel::Executor.new(workers)
|
85
|
-
else
|
86
|
-
raise ArgumentError, "#{with} is not a supported parallelization executor."
|
87
|
-
end
|
88
|
-
|
89
|
-
self.lock_threads = false if defined?(self.lock_threads) && with == :threads
|
90
|
-
|
91
|
-
Minitest.parallel_executor = executor
|
92
|
-
|
93
|
-
parallelize_me!
|
85
|
+
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
94
86
|
end
|
95
87
|
|
96
88
|
# Set up hook for parallel testing. This can be used if you have multiple
|
@@ -107,9 +99,7 @@ module ActiveSupport
|
|
107
99
|
# end
|
108
100
|
# end
|
109
101
|
def parallelize_setup(&block)
|
110
|
-
ActiveSupport::Testing::Parallelization.after_fork_hook
|
111
|
-
yield worker
|
112
|
-
end
|
102
|
+
ActiveSupport::Testing::Parallelization.after_fork_hook(&block)
|
113
103
|
end
|
114
104
|
|
115
105
|
# Clean up hook for parallel testing. This can be used to drop databases
|
@@ -126,9 +116,7 @@ module ActiveSupport
|
|
126
116
|
# end
|
127
117
|
# end
|
128
118
|
def parallelize_teardown(&block)
|
129
|
-
ActiveSupport::Testing::Parallelization.run_cleanup_hook
|
130
|
-
yield worker
|
131
|
-
end
|
119
|
+
ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
|
132
120
|
end
|
133
121
|
end
|
134
122
|
|
@@ -159,5 +147,9 @@ module ActiveSupport
|
|
159
147
|
alias :assert_not_same :refute_same
|
160
148
|
|
161
149
|
ActiveSupport.run_load_hooks(:active_support_test_case, self)
|
150
|
+
|
151
|
+
def inspect # :nodoc:
|
152
|
+
Object.instance_method(:to_s).bind_call(self)
|
153
|
+
end
|
162
154
|
end
|
163
155
|
end
|
@@ -99,7 +99,7 @@ module ActiveSupport
|
|
99
99
|
}
|
100
100
|
before = exps.map(&:call)
|
101
101
|
|
102
|
-
retval =
|
102
|
+
retval = _assert_nothing_raised_or_warn("assert_difference", &block)
|
103
103
|
|
104
104
|
expressions.zip(exps, before) do |(code, diff), exp, before_value|
|
105
105
|
error = "#{code.inspect} didn't change by #{diff}"
|
@@ -159,7 +159,7 @@ module ActiveSupport
|
|
159
159
|
# @object = 42
|
160
160
|
# end
|
161
161
|
#
|
162
|
-
# The keyword arguments
|
162
|
+
# The keyword arguments +:from+ and +:to+ can be given to specify the
|
163
163
|
# expected initial value and the expected value after the block was
|
164
164
|
# executed.
|
165
165
|
#
|
@@ -176,7 +176,7 @@ module ActiveSupport
|
|
176
176
|
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
|
177
177
|
|
178
178
|
before = exp.call
|
179
|
-
retval =
|
179
|
+
retval = _assert_nothing_raised_or_warn("assert_changes", &block)
|
180
180
|
|
181
181
|
unless from == UNTRACKED
|
182
182
|
error = "Expected change from #{from.inspect}"
|
@@ -207,16 +207,30 @@ module ActiveSupport
|
|
207
207
|
# post :create, params: { status: { ok: true } }
|
208
208
|
# end
|
209
209
|
#
|
210
|
+
# Provide the optional keyword argument :from to specify the expected
|
211
|
+
# initial value.
|
212
|
+
#
|
213
|
+
# assert_no_changes -> { Status.all_good? }, from: true do
|
214
|
+
# post :create, params: { status: { ok: true } }
|
215
|
+
# end
|
216
|
+
#
|
210
217
|
# An error message can be specified.
|
211
218
|
#
|
212
219
|
# assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
|
213
220
|
# post :create, params: { status: { ok: false } }
|
214
221
|
# end
|
215
|
-
def assert_no_changes(expression, message = nil, &block)
|
222
|
+
def assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
|
216
223
|
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
|
217
224
|
|
218
225
|
before = exp.call
|
219
|
-
retval =
|
226
|
+
retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
|
227
|
+
|
228
|
+
unless from == UNTRACKED
|
229
|
+
error = "Expected initial value of #{from.inspect}"
|
230
|
+
error = "#{message}.\n#{error}" if message
|
231
|
+
assert from === before, error
|
232
|
+
end
|
233
|
+
|
220
234
|
after = exp.call
|
221
235
|
|
222
236
|
error = "#{expression.inspect} changed"
|
@@ -230,6 +244,22 @@ module ActiveSupport
|
|
230
244
|
|
231
245
|
retval
|
232
246
|
end
|
247
|
+
|
248
|
+
private
|
249
|
+
def _assert_nothing_raised_or_warn(assertion, &block)
|
250
|
+
assert_nothing_raised(&block)
|
251
|
+
rescue Minitest::UnexpectedError => e
|
252
|
+
if tagged_logger && tagged_logger.warn?
|
253
|
+
warning = <<~MSG
|
254
|
+
#{self.class} - #{name}: #{e.error.class} raised.
|
255
|
+
If you expected this exception, use `assert_raises` as near to the code that raises as possible.
|
256
|
+
Other block based assertions (e.g. `#{assertion}`) can be used, as long as `assert_raises` is inside their block.
|
257
|
+
MSG
|
258
|
+
tagged_logger.warn warning
|
259
|
+
end
|
260
|
+
|
261
|
+
raise
|
262
|
+
end
|
233
263
|
end
|
234
264
|
end
|
235
265
|
end
|
@@ -4,7 +4,30 @@ require "active_support/deprecation"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module Testing
|
7
|
-
module Deprecation
|
7
|
+
module Deprecation
|
8
|
+
# Asserts that a matching deprecation warning was emitted by the given deprecator during the execution of the yielded block.
|
9
|
+
#
|
10
|
+
# assert_deprecated(/foo/, CustomDeprecator) do
|
11
|
+
# CustomDeprecator.warn "foo should no longer be used"
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# The +match+ object may be a +Regexp+, or +String+ appearing in the message.
|
15
|
+
#
|
16
|
+
# assert_deprecated('foo', CustomDeprecator) do
|
17
|
+
# CustomDeprecator.warn "foo should no longer be used"
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# If the +match+ is omitted (or explicitly +nil+), any deprecation warning will match.
|
21
|
+
#
|
22
|
+
# assert_deprecated(nil, CustomDeprecator) do
|
23
|
+
# CustomDeprecator.warn "foo should no longer be used"
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
|
27
|
+
#
|
28
|
+
# assert_deprecated do
|
29
|
+
# ActiveSupport::Deprecation.warn "foo should no longer be used"
|
30
|
+
# end
|
8
31
|
def assert_deprecated(match = nil, deprecator = nil, &block)
|
9
32
|
result, warnings = collect_deprecations(deprecator, &block)
|
10
33
|
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
|
@@ -15,12 +38,40 @@ module ActiveSupport
|
|
15
38
|
result
|
16
39
|
end
|
17
40
|
|
41
|
+
# Asserts that no deprecation warnings are emitted by the given deprecator during the execution of the yielded block.
|
42
|
+
#
|
43
|
+
# assert_not_deprecated(CustomDeprecator) do
|
44
|
+
# CustomDeprecator.warn "message" # fails assertion
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
|
48
|
+
#
|
49
|
+
# assert_not_deprecated do
|
50
|
+
# ActiveSupport::Deprecation.warn "message" # fails assertion
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# assert_not_deprecated do
|
54
|
+
# CustomDeprecator.warn "message" # passes assertion
|
55
|
+
# end
|
18
56
|
def assert_not_deprecated(deprecator = nil, &block)
|
19
57
|
result, deprecations = collect_deprecations(deprecator, &block)
|
20
58
|
assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
|
21
59
|
result
|
22
60
|
end
|
23
61
|
|
62
|
+
# Returns an array of all the deprecation warnings emitted by the given
|
63
|
+
# +deprecator+ during the execution of the yielded block.
|
64
|
+
#
|
65
|
+
# collect_deprecations(CustomDeprecator) do
|
66
|
+
# CustomDeprecator.warn "message"
|
67
|
+
# end # => ["message"]
|
68
|
+
#
|
69
|
+
# If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
|
70
|
+
#
|
71
|
+
# collect_deprecations do
|
72
|
+
# CustomDeprecator.warn "custom message"
|
73
|
+
# ActiveSupport::Deprecation.warn "message"
|
74
|
+
# end # => ["message"]
|
24
75
|
def collect_deprecations(deprecator = nil)
|
25
76
|
deprecator ||= ActiveSupport::Deprecation
|
26
77
|
old_behavior = deprecator.behavior
|
@@ -5,7 +5,7 @@ module ActiveSupport
|
|
5
5
|
module Isolation
|
6
6
|
require "thread"
|
7
7
|
|
8
|
-
def self.included(klass)
|
8
|
+
def self.included(klass) # :nodoc:
|
9
9
|
klass.class_eval do
|
10
10
|
parallelize_me!
|
11
11
|
end
|
@@ -25,45 +25,46 @@ module ActiveSupport
|
|
25
25
|
|
26
26
|
module Forking
|
27
27
|
def run_in_isolation(&blk)
|
28
|
-
read, write
|
29
|
-
|
30
|
-
|
28
|
+
IO.pipe do |read, write|
|
29
|
+
read.binmode
|
30
|
+
write.binmode
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
32
|
+
pid = fork do
|
33
|
+
read.close
|
34
|
+
yield
|
35
|
+
begin
|
36
|
+
if error?
|
37
|
+
failures.map! { |e|
|
38
|
+
begin
|
39
|
+
Marshal.dump e
|
40
|
+
e
|
41
|
+
rescue TypeError
|
42
|
+
ex = Exception.new e.message
|
43
|
+
ex.set_backtrace e.backtrace
|
44
|
+
Minitest::UnexpectedError.new ex
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
|
49
|
+
result = Marshal.dump(test_result)
|
47
50
|
end
|
48
|
-
|
49
|
-
result
|
51
|
+
|
52
|
+
write.puts [result].pack("m")
|
53
|
+
exit!
|
50
54
|
end
|
51
55
|
|
52
|
-
write.
|
53
|
-
|
56
|
+
write.close
|
57
|
+
result = read.read
|
58
|
+
Process.wait2(pid)
|
59
|
+
result.unpack1("m")
|
54
60
|
end
|
55
|
-
|
56
|
-
write.close
|
57
|
-
result = read.read
|
58
|
-
Process.wait2(pid)
|
59
|
-
result.unpack1("m")
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
63
64
|
module Subprocess
|
64
65
|
ORIG_ARGV = ARGV.dup unless defined?(ORIG_ARGV)
|
65
66
|
|
66
|
-
#
|
67
|
+
# Complicated H4X to get this working in windows / jruby with
|
67
68
|
# no forking.
|
68
69
|
def run_in_isolation(&blk)
|
69
70
|
require "tempfile"
|