activesupport 6.0.6.1 → 7.1.3.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +865 -438
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/active_support/actionable_error.rb +4 -2
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +30 -10
- data/lib/active_support/benchmarkable.rb +4 -3
- data/lib/active_support/broadcast_logger.rb +250 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +53 -20
- data/lib/active_support/cache/mem_cache_store.rb +208 -63
- data/lib/active_support/cache/memory_store.rb +120 -38
- data/lib/active_support/cache/null_store.rb +16 -2
- data/lib/active_support/cache/redis_cache_store.rb +201 -208
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +73 -66
- data/lib/active_support/cache.rb +539 -261
- data/lib/active_support/callbacks.rb +273 -142
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +53 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +19 -6
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +15 -13
- 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/benchmark.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +19 -29
- 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 +18 -16
- data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- 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 +19 -15
- data/lib/active_support/core_ext/digest/uuid.rb +30 -13
- data/lib/active_support/core_ext/enumerable.rb +146 -72
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +3 -4
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +4 -4
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +5 -5
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- 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/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +31 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +51 -20
- data/lib/active_support/core_ext/module/concerning.rb +14 -8
- data/lib/active_support/core_ext/module/delegation.rb +75 -42
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +1 -26
- data/lib/active_support/core_ext/name_error.rb +23 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +82 -73
- 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 +17 -1
- data/lib/active_support/core_ext/object/duplicable.rb +15 -4
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +52 -28
- 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.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +25 -6
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +6 -25
- data/lib/active_support/core_ext/range/conversions.rb +34 -13
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/securerandom.rb +25 -13
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +3 -2
- data/lib/active_support/core_ext/string/filters.rb +21 -15
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +51 -10
- data/lib/active_support/core_ext/string/inquiry.rb +2 -1
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +85 -194
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +46 -8
- data/lib/active_support/core_ext/time/conversions.rb +16 -13
- data/lib/active_support/core_ext/time/zones.rb +12 -28
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +54 -22
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- 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 -769
- data/lib/active_support/deprecation/behaviors.rb +77 -38
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/instance_delegator.rb +31 -5
- data/lib/active_support/deprecation/method_wrappers.rb +12 -28
- data/lib/active_support/deprecation/proxy_wrappers.rb +40 -25
- data/lib/active_support/deprecation/reporting.rb +76 -16
- data/lib/active_support/deprecation.rb +36 -4
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +150 -68
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +24 -12
- data/lib/active_support/duration.rb +136 -56
- data/lib/active_support/encrypted_configuration.rb +72 -9
- data/lib/active_support/encrypted_file.rb +46 -13
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +203 -0
- data/lib/active_support/evented_file_update_checker.rb +86 -137
- 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 +31 -12
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +79 -0
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +86 -42
- data/lib/active_support/html_safe_translation.rb +53 -0
- data/lib/active_support/i18n.rb +2 -1
- data/lib/active_support/i18n_railtie.rb +29 -27
- data/lib/active_support/inflector/inflections.rb +26 -9
- data/lib/active_support/inflector/methods.rb +54 -64
- data/lib/active_support/inflector/transliterate.rb +7 -5
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +6 -5
- data/lib/active_support/json/encoding.rb +31 -45
- data/lib/active_support/key_generator.rb +32 -7
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +10 -4
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +101 -32
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +24 -25
- data/lib/active_support/message_encryptor.rb +205 -58
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +237 -86
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +112 -46
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +35 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +15 -52
- data/lib/active_support/multibyte/unicode.rb +8 -122
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +310 -105
- data/lib/active_support/notifications/instrumenter.rb +113 -48
- data/lib/active_support/notifications.rb +56 -29
- data/lib/active_support/number_helper/number_converter.rb +15 -8
- 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_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -5
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
- data/lib/active_support/number_helper/rounding_helper.rb +12 -32
- data/lib/active_support/number_helper.rb +379 -304
- data/lib/active_support/option_merger.rb +11 -18
- data/lib/active_support/ordered_hash.rb +4 -4
- data/lib/active_support/ordered_options.rb +23 -3
- data/lib/active_support/parameter_filter.rb +104 -75
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +90 -6
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +18 -16
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +5 -3
- data/lib/active_support/subscriber.rb +23 -47
- data/lib/active_support/syntax_error_proxy.rb +70 -0
- data/lib/active_support/tagged_logging.rb +84 -23
- data/lib/active_support/test_case.rb +166 -27
- data/lib/active_support/testing/assertions.rb +73 -20
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +53 -2
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +30 -29
- data/lib/active_support/testing/method_call_assertions.rb +24 -11
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +16 -95
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/stream.rb +4 -6
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +89 -19
- data/lib/active_support/time_with_zone.rb +105 -70
- data/lib/active_support/values/time_zone.rb +59 -26
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +4 -11
- 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 +5 -5
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +9 -2
- data/lib/active_support/xml_mini.rb +7 -6
- data/lib/active_support.rb +40 -1
- metadata +127 -40
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
- data/lib/active_support/core_ext/hash/compact.rb +0 -5
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
- data/lib/active_support/core_ext/marshal.rb +0 -24
- data/lib/active_support/core_ext/module/reachable.rb +0 -6
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
- data/lib/active_support/core_ext/range/include_range.rb +0 -9
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -23
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/uri.rb +0 -25
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
- data/lib/active_support/per_thread_registry.rb +0 -60
@@ -4,33 +4,33 @@ require "active_support/concern"
|
|
4
4
|
require "active_support/descendants_tracker"
|
5
5
|
require "active_support/core_ext/array/extract_options"
|
6
6
|
require "active_support/core_ext/class/attribute"
|
7
|
-
require "active_support/core_ext/kernel/reporting"
|
8
|
-
require "active_support/core_ext/kernel/singleton_class"
|
9
7
|
require "active_support/core_ext/string/filters"
|
10
|
-
require "active_support/
|
8
|
+
require "active_support/core_ext/object/blank"
|
11
9
|
require "thread"
|
12
10
|
|
13
11
|
module ActiveSupport
|
14
|
-
#
|
12
|
+
# = Active Support \Callbacks
|
13
|
+
#
|
14
|
+
# \Callbacks are code hooks that are run at key points in an object's life cycle.
|
15
15
|
# The typical use case is to have a base class define a set of callbacks
|
16
16
|
# relevant to the other functionality it supplies, so that subclasses can
|
17
17
|
# install callbacks that enhance or modify the base functionality without
|
18
18
|
# needing to override or redefine methods of the base class.
|
19
19
|
#
|
20
20
|
# Mixing in this module allows you to define the events in the object's
|
21
|
-
# life cycle that will support callbacks (via
|
21
|
+
# life cycle that will support callbacks (via ClassMethods#define_callbacks),
|
22
22
|
# set the instance methods, procs, or callback objects to be called (via
|
23
|
-
#
|
23
|
+
# ClassMethods#set_callback), and run the installed callbacks at the
|
24
24
|
# appropriate times (via +run_callbacks+).
|
25
25
|
#
|
26
26
|
# By default callbacks are halted by throwing +:abort+.
|
27
|
-
# See
|
27
|
+
# See ClassMethods#define_callbacks for details.
|
28
28
|
#
|
29
29
|
# Three kinds of callbacks are supported: before callbacks, run before a
|
30
30
|
# certain event; after callbacks, run after the event; and around callbacks,
|
31
31
|
# blocks that surround the event, triggering it when they yield. Callback code
|
32
32
|
# can be contained in instance methods, procs or lambdas, or callback objects
|
33
|
-
# that respond to certain predetermined methods. See
|
33
|
+
# that respond to certain predetermined methods. See ClassMethods#set_callback
|
34
34
|
# for details.
|
35
35
|
#
|
36
36
|
# class Record
|
@@ -70,7 +70,7 @@ module ActiveSupport
|
|
70
70
|
class_attribute :__callbacks, instance_writer: false, default: {}
|
71
71
|
end
|
72
72
|
|
73
|
-
CALLBACK_FILTER_TYPES = [:before, :after, :around]
|
73
|
+
CALLBACK_FILTER_TYPES = [:before, :after, :around].freeze
|
74
74
|
|
75
75
|
# Runs the callbacks for the given event.
|
76
76
|
#
|
@@ -94,40 +94,15 @@ module ActiveSupport
|
|
94
94
|
# callback can be as noisy as it likes -- but when control has passed
|
95
95
|
# smoothly through and into the supplied block, we want as little evidence
|
96
96
|
# as possible that we were here.
|
97
|
-
def run_callbacks(kind)
|
97
|
+
def run_callbacks(kind, type = nil)
|
98
98
|
callbacks = __callbacks[kind.to_sym]
|
99
99
|
|
100
100
|
if callbacks.empty?
|
101
101
|
yield if block_given?
|
102
102
|
else
|
103
103
|
env = Filters::Environment.new(self, false, nil)
|
104
|
-
|
105
|
-
|
106
|
-
invoke_sequence = Proc.new do
|
107
|
-
skipped = nil
|
108
|
-
while true
|
109
|
-
current = next_sequence
|
110
|
-
current.invoke_before(env)
|
111
|
-
if current.final?
|
112
|
-
env.value = !env.halted && (!block_given? || yield)
|
113
|
-
elsif current.skip?(env)
|
114
|
-
(skipped ||= []) << current
|
115
|
-
next_sequence = next_sequence.nested
|
116
|
-
next
|
117
|
-
else
|
118
|
-
next_sequence = next_sequence.nested
|
119
|
-
begin
|
120
|
-
target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
|
121
|
-
target.send(method, *arguments, &block)
|
122
|
-
ensure
|
123
|
-
next_sequence = current
|
124
|
-
end
|
125
|
-
end
|
126
|
-
current.invoke_after(env)
|
127
|
-
skipped.pop.invoke_after(env) while skipped && skipped.first
|
128
|
-
break env.value
|
129
|
-
end
|
130
|
-
end
|
104
|
+
|
105
|
+
next_sequence = callbacks.compile(type)
|
131
106
|
|
132
107
|
# Common case: no 'around' callbacks defined
|
133
108
|
if next_sequence.final?
|
@@ -136,6 +111,33 @@ module ActiveSupport
|
|
136
111
|
next_sequence.invoke_after(env)
|
137
112
|
env.value
|
138
113
|
else
|
114
|
+
invoke_sequence = Proc.new do
|
115
|
+
skipped = nil
|
116
|
+
|
117
|
+
while true
|
118
|
+
current = next_sequence
|
119
|
+
current.invoke_before(env)
|
120
|
+
if current.final?
|
121
|
+
env.value = !env.halted && (!block_given? || yield)
|
122
|
+
elsif current.skip?(env)
|
123
|
+
(skipped ||= []) << current
|
124
|
+
next_sequence = next_sequence.nested
|
125
|
+
next
|
126
|
+
else
|
127
|
+
next_sequence = next_sequence.nested
|
128
|
+
begin
|
129
|
+
target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
|
130
|
+
target.send(method, *arguments, &block)
|
131
|
+
ensure
|
132
|
+
next_sequence = current
|
133
|
+
end
|
134
|
+
end
|
135
|
+
current.invoke_after(env)
|
136
|
+
skipped.pop.invoke_after(env) while skipped&.first
|
137
|
+
break env.value
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
139
141
|
invoke_sequence.call
|
140
142
|
end
|
141
143
|
end
|
@@ -145,7 +147,7 @@ module ActiveSupport
|
|
145
147
|
# A hook invoked every time a before callback is halted.
|
146
148
|
# This can be overridden in ActiveSupport::Callbacks implementors in order
|
147
149
|
# to provide better debugging/logging.
|
148
|
-
def halted_callback_hook(filter)
|
150
|
+
def halted_callback_hook(filter, name)
|
149
151
|
end
|
150
152
|
|
151
153
|
module Conditionals # :nodoc:
|
@@ -161,17 +163,17 @@ module ActiveSupport
|
|
161
163
|
Environment = Struct.new(:target, :halted, :value)
|
162
164
|
|
163
165
|
class Before
|
164
|
-
def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter)
|
166
|
+
def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter, name)
|
165
167
|
halted_lambda = chain_config[:terminator]
|
166
168
|
|
167
169
|
if user_conditions.any?
|
168
|
-
halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
|
170
|
+
halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
|
169
171
|
else
|
170
|
-
halting(callback_sequence, user_callback, halted_lambda, filter)
|
172
|
+
halting(callback_sequence, user_callback, halted_lambda, filter, name)
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
174
|
-
def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
|
176
|
+
def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
|
175
177
|
callback_sequence.before do |env|
|
176
178
|
target = env.target
|
177
179
|
value = env.value
|
@@ -181,7 +183,7 @@ module ActiveSupport
|
|
181
183
|
result_lambda = -> { user_callback.call target, value }
|
182
184
|
env.halted = halted_lambda.call(target, result_lambda)
|
183
185
|
if env.halted
|
184
|
-
target.send :halted_callback_hook, filter
|
186
|
+
target.send :halted_callback_hook, filter, name
|
185
187
|
end
|
186
188
|
end
|
187
189
|
|
@@ -190,7 +192,7 @@ module ActiveSupport
|
|
190
192
|
end
|
191
193
|
private_class_method :halting_and_conditional
|
192
194
|
|
193
|
-
def self.halting(callback_sequence, user_callback, halted_lambda, filter)
|
195
|
+
def self.halting(callback_sequence, user_callback, halted_lambda, filter, name)
|
194
196
|
callback_sequence.before do |env|
|
195
197
|
target = env.target
|
196
198
|
value = env.value
|
@@ -199,9 +201,8 @@ module ActiveSupport
|
|
199
201
|
unless halted
|
200
202
|
result_lambda = -> { user_callback.call target, value }
|
201
203
|
env.halted = halted_lambda.call(target, result_lambda)
|
202
|
-
|
203
204
|
if env.halted
|
204
|
-
target.send :halted_callback_hook, filter
|
205
|
+
target.send :halted_callback_hook, filter, name
|
205
206
|
end
|
206
207
|
end
|
207
208
|
|
@@ -279,7 +280,7 @@ module ActiveSupport
|
|
279
280
|
end
|
280
281
|
end
|
281
282
|
|
282
|
-
class Callback
|
283
|
+
class Callback # :nodoc:#
|
283
284
|
def self.build(chain, filter, kind, options)
|
284
285
|
if filter.is_a?(String)
|
285
286
|
raise ArgumentError, <<-MSG.squish
|
@@ -292,21 +293,17 @@ module ActiveSupport
|
|
292
293
|
end
|
293
294
|
|
294
295
|
attr_accessor :kind, :name
|
295
|
-
attr_reader :chain_config
|
296
|
+
attr_reader :chain_config, :filter
|
296
297
|
|
297
298
|
def initialize(name, filter, kind, options, chain_config)
|
298
299
|
@chain_config = chain_config
|
299
300
|
@name = name
|
300
301
|
@kind = kind
|
301
302
|
@filter = filter
|
302
|
-
@
|
303
|
-
@
|
304
|
-
@unless = check_conditionals(Array(options[:unless]))
|
303
|
+
@if = check_conditionals(options[:if])
|
304
|
+
@unless = check_conditionals(options[:unless])
|
305
305
|
end
|
306
306
|
|
307
|
-
def filter; @key; end
|
308
|
-
def raw_filter; @filter; end
|
309
|
-
|
310
307
|
def merge_conditional_options(chain, if_option:, unless_option:)
|
311
308
|
options = {
|
312
309
|
if: @if.dup,
|
@@ -339,7 +336,7 @@ module ActiveSupport
|
|
339
336
|
|
340
337
|
case kind
|
341
338
|
when :before
|
342
|
-
Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter)
|
339
|
+
Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter, name)
|
343
340
|
when :after
|
344
341
|
Filters::After.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config)
|
345
342
|
when :around
|
@@ -352,8 +349,14 @@ module ActiveSupport
|
|
352
349
|
end
|
353
350
|
|
354
351
|
private
|
352
|
+
EMPTY_ARRAY = [].freeze
|
353
|
+
private_constant :EMPTY_ARRAY
|
354
|
+
|
355
355
|
def check_conditionals(conditionals)
|
356
|
-
if conditionals.
|
356
|
+
return EMPTY_ARRAY if conditionals.blank?
|
357
|
+
|
358
|
+
conditionals = Array(conditionals)
|
359
|
+
if conditionals.any?(String)
|
357
360
|
raise ArgumentError, <<-MSG.squish
|
358
361
|
Passing string to be evaluated in :if and :unless conditional
|
359
362
|
options is not supported. Pass a symbol for an instance method,
|
@@ -361,16 +364,7 @@ module ActiveSupport
|
|
361
364
|
MSG
|
362
365
|
end
|
363
366
|
|
364
|
-
conditionals
|
365
|
-
end
|
366
|
-
|
367
|
-
def compute_identifier(filter)
|
368
|
-
case filter
|
369
|
-
when ::Proc
|
370
|
-
filter.object_id
|
371
|
-
else
|
372
|
-
filter
|
373
|
-
end
|
367
|
+
conditionals.freeze
|
374
368
|
end
|
375
369
|
|
376
370
|
def conditions_lambdas
|
@@ -381,60 +375,153 @@ module ActiveSupport
|
|
381
375
|
|
382
376
|
# A future invocation of user-supplied code (either as a callback,
|
383
377
|
# or a condition filter).
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
378
|
+
module CallTemplate # :nodoc:
|
379
|
+
class MethodCall
|
380
|
+
def initialize(method)
|
381
|
+
@method_name = method
|
382
|
+
end
|
383
|
+
|
384
|
+
# Return the parts needed to make this call, with the given
|
385
|
+
# input values.
|
386
|
+
#
|
387
|
+
# Returns an array of the form:
|
388
|
+
#
|
389
|
+
# [target, block, method, *arguments]
|
390
|
+
#
|
391
|
+
# This array can be used as such:
|
392
|
+
#
|
393
|
+
# target.send(method, *arguments, &block)
|
394
|
+
#
|
395
|
+
# The actual invocation is left up to the caller to minimize
|
396
|
+
# call stack pollution.
|
397
|
+
def expand(target, value, block)
|
398
|
+
[target, block, @method_name]
|
399
|
+
end
|
400
|
+
|
401
|
+
def make_lambda
|
402
|
+
lambda do |target, value, &block|
|
403
|
+
target.send(@method_name, &block)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def inverted_lambda
|
408
|
+
lambda do |target, value, &block|
|
409
|
+
!target.send(@method_name, &block)
|
410
|
+
end
|
411
|
+
end
|
390
412
|
end
|
391
413
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
def expand(target, value, block)
|
406
|
-
result = @arguments.map { |arg|
|
407
|
-
case arg
|
408
|
-
when :value; value
|
409
|
-
when :target; target
|
410
|
-
when :block; block || raise(ArgumentError)
|
414
|
+
class ObjectCall
|
415
|
+
def initialize(target, method)
|
416
|
+
@override_target = target
|
417
|
+
@method_name = method
|
418
|
+
end
|
419
|
+
|
420
|
+
def expand(target, value, block)
|
421
|
+
[@override_target || target, block, @method_name, target]
|
422
|
+
end
|
423
|
+
|
424
|
+
def make_lambda
|
425
|
+
lambda do |target, value, &block|
|
426
|
+
(@override_target || target).send(@method_name, target, &block)
|
411
427
|
end
|
412
|
-
|
428
|
+
end
|
413
429
|
|
414
|
-
|
415
|
-
|
416
|
-
|
430
|
+
def inverted_lambda
|
431
|
+
lambda do |target, value, &block|
|
432
|
+
!(@override_target || target).send(@method_name, target, &block)
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
417
436
|
|
418
|
-
|
419
|
-
|
420
|
-
|
437
|
+
class InstanceExec0
|
438
|
+
def initialize(block)
|
439
|
+
@override_block = block
|
440
|
+
end
|
441
|
+
|
442
|
+
def expand(target, value, block)
|
443
|
+
[target, @override_block, :instance_exec]
|
444
|
+
end
|
445
|
+
|
446
|
+
def make_lambda
|
447
|
+
lambda do |target, value, &block|
|
448
|
+
target.instance_exec(&@override_block)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def inverted_lambda
|
453
|
+
lambda do |target, value, &block|
|
454
|
+
!target.instance_exec(&@override_block)
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
class InstanceExec1
|
460
|
+
def initialize(block)
|
461
|
+
@override_block = block
|
462
|
+
end
|
463
|
+
|
464
|
+
def expand(target, value, block)
|
465
|
+
[target, @override_block, :instance_exec, target]
|
466
|
+
end
|
467
|
+
|
468
|
+
def make_lambda
|
469
|
+
lambda do |target, value, &block|
|
470
|
+
target.instance_exec(target, &@override_block)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
def inverted_lambda
|
475
|
+
lambda do |target, value, &block|
|
476
|
+
!target.instance_exec(target, &@override_block)
|
477
|
+
end
|
478
|
+
end
|
421
479
|
end
|
422
480
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
481
|
+
class InstanceExec2
|
482
|
+
def initialize(block)
|
483
|
+
@override_block = block
|
484
|
+
end
|
485
|
+
|
486
|
+
def expand(target, value, block)
|
487
|
+
raise ArgumentError unless block
|
488
|
+
[target, @override_block || block, :instance_exec, target, block]
|
489
|
+
end
|
490
|
+
|
491
|
+
def make_lambda
|
492
|
+
lambda do |target, value, &block|
|
493
|
+
raise ArgumentError unless block
|
494
|
+
target.instance_exec(target, block, &@override_block)
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
def inverted_lambda
|
499
|
+
lambda do |target, value, &block|
|
500
|
+
raise ArgumentError unless block
|
501
|
+
!target.instance_exec(target, block, &@override_block)
|
502
|
+
end
|
429
503
|
end
|
430
504
|
end
|
431
505
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
506
|
+
class ProcCall
|
507
|
+
def initialize(target)
|
508
|
+
@override_target = target
|
509
|
+
end
|
510
|
+
|
511
|
+
def expand(target, value, block)
|
512
|
+
[@override_target || target, block, :call, target, value]
|
513
|
+
end
|
514
|
+
|
515
|
+
def make_lambda
|
516
|
+
lambda do |target, value, &block|
|
517
|
+
(@override_target || target).call(target, value, &block)
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
def inverted_lambda
|
522
|
+
lambda do |target, value, &block|
|
523
|
+
!(@override_target || target).call(target, value, &block)
|
524
|
+
end
|
438
525
|
end
|
439
526
|
end
|
440
527
|
|
@@ -449,21 +536,19 @@ module ActiveSupport
|
|
449
536
|
def self.build(filter, callback)
|
450
537
|
case filter
|
451
538
|
when Symbol
|
452
|
-
new(
|
539
|
+
MethodCall.new(filter)
|
453
540
|
when Conditionals::Value
|
454
|
-
new(filter
|
541
|
+
ProcCall.new(filter)
|
455
542
|
when ::Proc
|
456
543
|
if filter.arity > 1
|
457
|
-
new(
|
544
|
+
InstanceExec2.new(filter)
|
458
545
|
elsif filter.arity > 0
|
459
|
-
new(
|
546
|
+
InstanceExec1.new(filter)
|
460
547
|
else
|
461
|
-
new(
|
548
|
+
InstanceExec0.new(filter)
|
462
549
|
end
|
463
550
|
else
|
464
|
-
|
465
|
-
|
466
|
-
new(filter, method_to_call, [:target], nil)
|
551
|
+
ObjectCall.new(filter, callback.current_scopes.join("_").to_sym)
|
467
552
|
end
|
468
553
|
end
|
469
554
|
end
|
@@ -518,7 +603,7 @@ module ActiveSupport
|
|
518
603
|
end
|
519
604
|
end
|
520
605
|
|
521
|
-
class CallbackChain
|
606
|
+
class CallbackChain # :nodoc:
|
522
607
|
include Enumerable
|
523
608
|
|
524
609
|
attr_reader :name, :config
|
@@ -530,7 +615,8 @@ module ActiveSupport
|
|
530
615
|
terminator: default_terminator
|
531
616
|
}.merge!(config)
|
532
617
|
@chain = []
|
533
|
-
@
|
618
|
+
@all_callbacks = nil
|
619
|
+
@single_callbacks = {}
|
534
620
|
@mutex = Mutex.new
|
535
621
|
end
|
536
622
|
|
@@ -539,32 +625,45 @@ module ActiveSupport
|
|
539
625
|
def empty?; @chain.empty?; end
|
540
626
|
|
541
627
|
def insert(index, o)
|
542
|
-
@
|
628
|
+
@all_callbacks = nil
|
629
|
+
@single_callbacks.clear
|
543
630
|
@chain.insert(index, o)
|
544
631
|
end
|
545
632
|
|
546
633
|
def delete(o)
|
547
|
-
@
|
634
|
+
@all_callbacks = nil
|
635
|
+
@single_callbacks.clear
|
548
636
|
@chain.delete(o)
|
549
637
|
end
|
550
638
|
|
551
639
|
def clear
|
552
|
-
@
|
640
|
+
@all_callbacks = nil
|
641
|
+
@single_callbacks.clear
|
553
642
|
@chain.clear
|
554
643
|
self
|
555
644
|
end
|
556
645
|
|
557
646
|
def initialize_copy(other)
|
558
|
-
@
|
647
|
+
@all_callbacks = nil
|
648
|
+
@single_callbacks = {}
|
559
649
|
@chain = other.chain.dup
|
560
650
|
@mutex = Mutex.new
|
561
651
|
end
|
562
652
|
|
563
|
-
def compile
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
653
|
+
def compile(type)
|
654
|
+
if type.nil?
|
655
|
+
@all_callbacks || @mutex.synchronize do
|
656
|
+
final_sequence = CallbackSequence.new
|
657
|
+
@all_callbacks ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback|
|
658
|
+
callback.apply(callback_sequence)
|
659
|
+
end
|
660
|
+
end
|
661
|
+
else
|
662
|
+
@single_callbacks[type] || @mutex.synchronize do
|
663
|
+
final_sequence = CallbackSequence.new
|
664
|
+
@single_callbacks[type] ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback|
|
665
|
+
type == callback.kind ? callback.apply(callback_sequence) : callback_sequence
|
666
|
+
end
|
568
667
|
end
|
569
668
|
end
|
570
669
|
end
|
@@ -582,19 +681,22 @@ module ActiveSupport
|
|
582
681
|
|
583
682
|
private
|
584
683
|
def append_one(callback)
|
585
|
-
@
|
684
|
+
@all_callbacks = nil
|
685
|
+
@single_callbacks.clear
|
586
686
|
remove_duplicates(callback)
|
587
687
|
@chain.push(callback)
|
588
688
|
end
|
589
689
|
|
590
690
|
def prepend_one(callback)
|
591
|
-
@
|
691
|
+
@all_callbacks = nil
|
692
|
+
@single_callbacks.clear
|
592
693
|
remove_duplicates(callback)
|
593
694
|
@chain.unshift(callback)
|
594
695
|
end
|
595
696
|
|
596
697
|
def remove_duplicates(callback)
|
597
|
-
@
|
698
|
+
@all_callbacks = nil
|
699
|
+
@single_callbacks.clear
|
598
700
|
@chain.delete_if { |c| callback.duplicates?(c) }
|
599
701
|
end
|
600
702
|
|
@@ -620,8 +722,8 @@ module ActiveSupport
|
|
620
722
|
|
621
723
|
# This is used internally to append, prepend and skip callbacks to the
|
622
724
|
# CallbackChain.
|
623
|
-
def __update_callbacks(name)
|
624
|
-
|
725
|
+
def __update_callbacks(name) # :nodoc:
|
726
|
+
self.descendants.prepend(self).reverse_each do |target|
|
625
727
|
chain = target.get_callbacks name
|
626
728
|
yield target, chain.dup
|
627
729
|
end
|
@@ -641,7 +743,7 @@ module ActiveSupport
|
|
641
743
|
#
|
642
744
|
# The callback can be specified as a symbol naming an instance method; as a
|
643
745
|
# proc, lambda, or block; or as an object that responds to a certain method
|
644
|
-
# determined by the <tt>:scope</tt> argument to
|
746
|
+
# determined by the <tt>:scope</tt> argument to #define_callbacks.
|
645
747
|
#
|
646
748
|
# If a proc, lambda, or block is given, its body is evaluated in the context
|
647
749
|
# of the current object. It can also optionally accept the current object as
|
@@ -685,14 +787,39 @@ module ActiveSupport
|
|
685
787
|
end
|
686
788
|
end
|
687
789
|
|
688
|
-
# Skip a previously set callback. Like
|
790
|
+
# Skip a previously set callback. Like #set_callback, <tt>:if</tt> or
|
689
791
|
# <tt>:unless</tt> options may be passed in order to control when the
|
690
792
|
# callback is skipped.
|
691
793
|
#
|
692
|
-
#
|
693
|
-
#
|
794
|
+
# Note: this example uses +PersonRecord+ and +#saving_message+, which you
|
795
|
+
# can see defined here[rdoc-ref:ActiveSupport::Callbacks]
|
796
|
+
#
|
797
|
+
# class Writer < PersonRecord
|
798
|
+
# attr_accessor :age
|
799
|
+
# skip_callback :save, :before, :saving_message, if: -> { age > 18 }
|
694
800
|
# end
|
695
801
|
#
|
802
|
+
# When if option returns true, callback is skipped.
|
803
|
+
#
|
804
|
+
# writer = Writer.new
|
805
|
+
# writer.age = 20
|
806
|
+
# writer.save
|
807
|
+
#
|
808
|
+
# Output:
|
809
|
+
# - save
|
810
|
+
# saved
|
811
|
+
#
|
812
|
+
# When if option returns false, callback is NOT skipped.
|
813
|
+
#
|
814
|
+
# young_writer = Writer.new
|
815
|
+
# young_writer.age = 17
|
816
|
+
# young_writer.save
|
817
|
+
#
|
818
|
+
# Output:
|
819
|
+
# saving...
|
820
|
+
# - save
|
821
|
+
# saved
|
822
|
+
#
|
696
823
|
# An <tt>ArgumentError</tt> will be raised if the callback has not
|
697
824
|
# already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
|
698
825
|
def skip_callback(name, *filter_list, &block)
|
@@ -723,7 +850,7 @@ module ActiveSupport
|
|
723
850
|
def reset_callbacks(name)
|
724
851
|
callbacks = get_callbacks name
|
725
852
|
|
726
|
-
|
853
|
+
self.descendants.each do |target|
|
727
854
|
chain = target.get_callbacks(name).dup
|
728
855
|
callbacks.each { |c| chain.delete(c) }
|
729
856
|
target.set_callbacks name, chain
|
@@ -809,14 +936,14 @@ module ActiveSupport
|
|
809
936
|
# <tt>!</tt>, <tt>?</tt> or <tt>=</tt>.
|
810
937
|
#
|
811
938
|
# Calling +define_callbacks+ multiple times with the same +names+ will
|
812
|
-
# overwrite previous callbacks registered with
|
939
|
+
# overwrite previous callbacks registered with #set_callback.
|
813
940
|
def define_callbacks(*names)
|
814
941
|
options = names.extract_options!
|
815
942
|
|
816
943
|
names.each do |name|
|
817
944
|
name = name.to_sym
|
818
945
|
|
819
|
-
([self] +
|
946
|
+
([self] + self.descendants).each do |target|
|
820
947
|
target.set_callbacks name, CallbackChain.new(name, options)
|
821
948
|
end
|
822
949
|
|
@@ -846,7 +973,11 @@ module ActiveSupport
|
|
846
973
|
end
|
847
974
|
|
848
975
|
def set_callbacks(name, callbacks) # :nodoc:
|
849
|
-
|
976
|
+
unless singleton_class.method_defined?(:__callbacks, false)
|
977
|
+
self.__callbacks = __callbacks.dup
|
978
|
+
end
|
979
|
+
self.__callbacks[name.to_sym] = callbacks
|
980
|
+
self.__callbacks
|
850
981
|
end
|
851
982
|
end
|
852
983
|
end
|