activesupport 6.1.0 → 7.1.5.1
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 +1075 -325
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +4 -2
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +32 -7
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +251 -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 +201 -62
- data/lib/active_support/cache/memory_store.rb +86 -24
- data/lib/active_support/cache/null_store.rb +16 -2
- data/lib/active_support/cache/redis_cache_store.rb +186 -193
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +63 -71
- data/lib/active_support/cache.rb +487 -249
- data/lib/active_support/callbacks.rb +227 -105
- data/lib/active_support/code_generator.rb +70 -0
- data/lib/active_support/concern.rb +9 -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 +18 -5
- data/lib/active_support/configuration_file.rb +7 -2
- 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/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +37 -26
- 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 +16 -15
- data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -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 +19 -15
- data/lib/active_support/core_ext/digest/uuid.rb +30 -13
- data/lib/active_support/core_ext/enumerable.rb +85 -83
- 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 +1 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- 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 +8 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +49 -22
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +81 -43
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/name_error.rb +2 -8
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +82 -77
- 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 +31 -11
- 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 +49 -27
- 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 +0 -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/securerandom.rb +25 -13
- data/lib/active_support/core_ext/string/conversions.rb +2 -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 +17 -10
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +85 -165
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +30 -8
- data/lib/active_support/core_ext/time/conversions.rb +15 -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.rb +47 -20
- 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 -788
- data/lib/active_support/deprecation/behaviors.rb +66 -40
- 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 +6 -8
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +9 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +38 -23
- data/lib/active_support/deprecation/reporting.rb +43 -26
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +150 -72
- 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 +9 -3
- data/lib/active_support/duration.rb +83 -52
- data/lib/active_support/encrypted_configuration.rb +72 -9
- data/lib/active_support/encrypted_file.rb +29 -13
- data/lib/active_support/environment_inquirer.rb +23 -3
- 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 +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 +44 -22
- 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 +28 -11
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +44 -19
- 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 +21 -14
- data/lib/active_support/inflector/inflections.rb +25 -7
- data/lib/active_support/inflector/methods.rb +50 -64
- data/lib/active_support/inflector/transliterate.rb +4 -2
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +27 -45
- data/lib/active_support/key_generator.rb +31 -6
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +4 -2
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +97 -35
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_thread_safe_level.rb +11 -34
- data/lib/active_support/message_encryptor.rb +206 -56
- 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 +235 -84
- 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_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +12 -11
- data/lib/active_support/multibyte/unicode.rb +9 -49
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +304 -114
- data/lib/active_support/notifications/instrumenter.rb +117 -35
- data/lib/active_support/notifications.rb +25 -25
- data/lib/active_support/number_helper/number_converter.rb +14 -7
- 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 +4 -4
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +10 -6
- data/lib/active_support/number_helper/rounding_helper.rb +2 -6
- data/lib/active_support/number_helper.rb +379 -319
- data/lib/active_support/option_merger.rb +10 -18
- data/lib/active_support/ordered_hash.rb +4 -4
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/parameter_filter.rb +105 -81
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +83 -21
- data/lib/active_support/reloader.rb +13 -5
- 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 +18 -11
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/string_inquirer.rb +3 -3
- data/lib/active_support/subscriber.rb +11 -40
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +65 -25
- data/lib/active_support/test_case.rb +166 -27
- data/lib/active_support/testing/assertions.rb +61 -15
- 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 +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 +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +2 -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 +49 -16
- data/lib/active_support/time_with_zone.rb +39 -28
- data/lib/active_support/values/time_zone.rb +50 -18
- 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 +2 -2
- data/lib/active_support/xml_mini.rb +7 -6
- data/lib/active_support.rb +28 -1
- metadata +150 -18
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/uri.rb +0 -29
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
- data/lib/active_support/per_thread_registry.rb +0 -60
@@ -5,29 +5,32 @@ 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
7
|
require "active_support/core_ext/string/filters"
|
8
|
+
require "active_support/core_ext/object/blank"
|
8
9
|
require "thread"
|
9
10
|
|
10
11
|
module ActiveSupport
|
11
|
-
#
|
12
|
+
# = Active Support \Callbacks
|
13
|
+
#
|
14
|
+
# \Callbacks are code hooks that are run at key points in an object's life cycle.
|
12
15
|
# The typical use case is to have a base class define a set of callbacks
|
13
16
|
# relevant to the other functionality it supplies, so that subclasses can
|
14
17
|
# install callbacks that enhance or modify the base functionality without
|
15
18
|
# needing to override or redefine methods of the base class.
|
16
19
|
#
|
17
20
|
# Mixing in this module allows you to define the events in the object's
|
18
|
-
# life cycle that will support callbacks (via
|
21
|
+
# life cycle that will support callbacks (via ClassMethods#define_callbacks),
|
19
22
|
# set the instance methods, procs, or callback objects to be called (via
|
20
|
-
#
|
23
|
+
# ClassMethods#set_callback), and run the installed callbacks at the
|
21
24
|
# appropriate times (via +run_callbacks+).
|
22
25
|
#
|
23
26
|
# By default callbacks are halted by throwing +:abort+.
|
24
|
-
# See
|
27
|
+
# See ClassMethods#define_callbacks for details.
|
25
28
|
#
|
26
29
|
# Three kinds of callbacks are supported: before callbacks, run before a
|
27
30
|
# certain event; after callbacks, run after the event; and around callbacks,
|
28
31
|
# blocks that surround the event, triggering it when they yield. Callback code
|
29
32
|
# can be contained in instance methods, procs or lambdas, or callback objects
|
30
|
-
# that respond to certain predetermined methods. See
|
33
|
+
# that respond to certain predetermined methods. See ClassMethods#set_callback
|
31
34
|
# for details.
|
32
35
|
#
|
33
36
|
# class Record
|
@@ -67,7 +70,7 @@ module ActiveSupport
|
|
67
70
|
class_attribute :__callbacks, instance_writer: false, default: {}
|
68
71
|
end
|
69
72
|
|
70
|
-
CALLBACK_FILTER_TYPES = [:before, :after, :around]
|
73
|
+
CALLBACK_FILTER_TYPES = [:before, :after, :around].freeze
|
71
74
|
|
72
75
|
# Runs the callbacks for the given event.
|
73
76
|
#
|
@@ -91,14 +94,15 @@ module ActiveSupport
|
|
91
94
|
# callback can be as noisy as it likes -- but when control has passed
|
92
95
|
# smoothly through and into the supplied block, we want as little evidence
|
93
96
|
# as possible that we were here.
|
94
|
-
def run_callbacks(kind)
|
97
|
+
def run_callbacks(kind, type = nil)
|
95
98
|
callbacks = __callbacks[kind.to_sym]
|
96
99
|
|
97
100
|
if callbacks.empty?
|
98
101
|
yield if block_given?
|
99
102
|
else
|
100
103
|
env = Filters::Environment.new(self, false, nil)
|
101
|
-
|
104
|
+
|
105
|
+
next_sequence = callbacks.compile(type)
|
102
106
|
|
103
107
|
# Common case: no 'around' callbacks defined
|
104
108
|
if next_sequence.final?
|
@@ -276,7 +280,7 @@ module ActiveSupport
|
|
276
280
|
end
|
277
281
|
end
|
278
282
|
|
279
|
-
class Callback
|
283
|
+
class Callback # :nodoc:#
|
280
284
|
def self.build(chain, filter, kind, options)
|
281
285
|
if filter.is_a?(String)
|
282
286
|
raise ArgumentError, <<-MSG.squish
|
@@ -289,21 +293,17 @@ module ActiveSupport
|
|
289
293
|
end
|
290
294
|
|
291
295
|
attr_accessor :kind, :name
|
292
|
-
attr_reader :chain_config
|
296
|
+
attr_reader :chain_config, :filter
|
293
297
|
|
294
298
|
def initialize(name, filter, kind, options, chain_config)
|
295
299
|
@chain_config = chain_config
|
296
300
|
@name = name
|
297
301
|
@kind = kind
|
298
302
|
@filter = filter
|
299
|
-
@key = compute_identifier filter
|
300
303
|
@if = check_conditionals(options[:if])
|
301
304
|
@unless = check_conditionals(options[:unless])
|
302
305
|
end
|
303
306
|
|
304
|
-
def filter; @key; end
|
305
|
-
def raw_filter; @filter; end
|
306
|
-
|
307
307
|
def merge_conditional_options(chain, if_option:, unless_option:)
|
308
308
|
options = {
|
309
309
|
if: @if.dup,
|
@@ -356,7 +356,7 @@ module ActiveSupport
|
|
356
356
|
return EMPTY_ARRAY if conditionals.blank?
|
357
357
|
|
358
358
|
conditionals = Array(conditionals)
|
359
|
-
if conditionals.any?
|
359
|
+
if conditionals.any?(String)
|
360
360
|
raise ArgumentError, <<-MSG.squish
|
361
361
|
Passing string to be evaluated in :if and :unless conditional
|
362
362
|
options is not supported. Pass a symbol for an instance method,
|
@@ -367,15 +367,6 @@ module ActiveSupport
|
|
367
367
|
conditionals.freeze
|
368
368
|
end
|
369
369
|
|
370
|
-
def compute_identifier(filter)
|
371
|
-
case filter
|
372
|
-
when ::Proc
|
373
|
-
filter.object_id
|
374
|
-
else
|
375
|
-
filter
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
370
|
def conditions_lambdas
|
380
371
|
@if.map { |c| CallTemplate.build(c, self).make_lambda } +
|
381
372
|
@unless.map { |c| CallTemplate.build(c, self).inverted_lambda }
|
@@ -384,56 +375,153 @@ module ActiveSupport
|
|
384
375
|
|
385
376
|
# A future invocation of user-supplied code (either as a callback,
|
386
377
|
# or a condition filter).
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
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
|
393
412
|
end
|
394
413
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
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)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
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
|
436
|
+
|
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
|
410
467
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
when :target then expanded << target
|
415
|
-
when :block then expanded << (block || raise(ArgumentError))
|
468
|
+
def make_lambda
|
469
|
+
lambda do |target, value, &block|
|
470
|
+
target.instance_exec(target, &@override_block)
|
416
471
|
end
|
417
472
|
end
|
418
473
|
|
419
|
-
|
474
|
+
def inverted_lambda
|
475
|
+
lambda do |target, value, &block|
|
476
|
+
!target.instance_exec(target, &@override_block)
|
477
|
+
end
|
478
|
+
end
|
420
479
|
end
|
421
480
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
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
|
428
503
|
end
|
429
504
|
end
|
430
505
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
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
|
437
525
|
end
|
438
526
|
end
|
439
527
|
|
@@ -448,21 +536,19 @@ module ActiveSupport
|
|
448
536
|
def self.build(filter, callback)
|
449
537
|
case filter
|
450
538
|
when Symbol
|
451
|
-
new(
|
539
|
+
MethodCall.new(filter)
|
452
540
|
when Conditionals::Value
|
453
|
-
new(filter
|
541
|
+
ProcCall.new(filter)
|
454
542
|
when ::Proc
|
455
543
|
if filter.arity > 1
|
456
|
-
new(
|
544
|
+
InstanceExec2.new(filter)
|
457
545
|
elsif filter.arity > 0
|
458
|
-
new(
|
546
|
+
InstanceExec1.new(filter)
|
459
547
|
else
|
460
|
-
new(
|
548
|
+
InstanceExec0.new(filter)
|
461
549
|
end
|
462
550
|
else
|
463
|
-
|
464
|
-
|
465
|
-
new(filter, method_to_call, [:target], nil)
|
551
|
+
ObjectCall.new(filter, callback.current_scopes.join("_").to_sym)
|
466
552
|
end
|
467
553
|
end
|
468
554
|
end
|
@@ -517,7 +603,7 @@ module ActiveSupport
|
|
517
603
|
end
|
518
604
|
end
|
519
605
|
|
520
|
-
class CallbackChain
|
606
|
+
class CallbackChain # :nodoc:
|
521
607
|
include Enumerable
|
522
608
|
|
523
609
|
attr_reader :name, :config
|
@@ -529,7 +615,8 @@ module ActiveSupport
|
|
529
615
|
terminator: default_terminator
|
530
616
|
}.merge!(config)
|
531
617
|
@chain = []
|
532
|
-
@
|
618
|
+
@all_callbacks = nil
|
619
|
+
@single_callbacks = {}
|
533
620
|
@mutex = Mutex.new
|
534
621
|
end
|
535
622
|
|
@@ -538,32 +625,45 @@ module ActiveSupport
|
|
538
625
|
def empty?; @chain.empty?; end
|
539
626
|
|
540
627
|
def insert(index, o)
|
541
|
-
@
|
628
|
+
@all_callbacks = nil
|
629
|
+
@single_callbacks.clear
|
542
630
|
@chain.insert(index, o)
|
543
631
|
end
|
544
632
|
|
545
633
|
def delete(o)
|
546
|
-
@
|
634
|
+
@all_callbacks = nil
|
635
|
+
@single_callbacks.clear
|
547
636
|
@chain.delete(o)
|
548
637
|
end
|
549
638
|
|
550
639
|
def clear
|
551
|
-
@
|
640
|
+
@all_callbacks = nil
|
641
|
+
@single_callbacks.clear
|
552
642
|
@chain.clear
|
553
643
|
self
|
554
644
|
end
|
555
645
|
|
556
646
|
def initialize_copy(other)
|
557
|
-
@
|
647
|
+
@all_callbacks = nil
|
648
|
+
@single_callbacks = {}
|
558
649
|
@chain = other.chain.dup
|
559
650
|
@mutex = Mutex.new
|
560
651
|
end
|
561
652
|
|
562
|
-
def compile
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
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
|
567
667
|
end
|
568
668
|
end
|
569
669
|
end
|
@@ -581,19 +681,22 @@ module ActiveSupport
|
|
581
681
|
|
582
682
|
private
|
583
683
|
def append_one(callback)
|
584
|
-
@
|
684
|
+
@all_callbacks = nil
|
685
|
+
@single_callbacks.clear
|
585
686
|
remove_duplicates(callback)
|
586
687
|
@chain.push(callback)
|
587
688
|
end
|
588
689
|
|
589
690
|
def prepend_one(callback)
|
590
|
-
@
|
691
|
+
@all_callbacks = nil
|
692
|
+
@single_callbacks.clear
|
591
693
|
remove_duplicates(callback)
|
592
694
|
@chain.unshift(callback)
|
593
695
|
end
|
594
696
|
|
595
697
|
def remove_duplicates(callback)
|
596
|
-
@
|
698
|
+
@all_callbacks = nil
|
699
|
+
@single_callbacks.clear
|
597
700
|
@chain.delete_if { |c| callback.duplicates?(c) }
|
598
701
|
end
|
599
702
|
|
@@ -619,8 +722,8 @@ module ActiveSupport
|
|
619
722
|
|
620
723
|
# This is used internally to append, prepend and skip callbacks to the
|
621
724
|
# CallbackChain.
|
622
|
-
def __update_callbacks(name)
|
623
|
-
|
725
|
+
def __update_callbacks(name) # :nodoc:
|
726
|
+
self.descendants.prepend(self).reverse_each do |target|
|
624
727
|
chain = target.get_callbacks name
|
625
728
|
yield target, chain.dup
|
626
729
|
end
|
@@ -640,7 +743,7 @@ module ActiveSupport
|
|
640
743
|
#
|
641
744
|
# The callback can be specified as a symbol naming an instance method; as a
|
642
745
|
# proc, lambda, or block; or as an object that responds to a certain method
|
643
|
-
# determined by the <tt>:scope</tt> argument to
|
746
|
+
# determined by the <tt>:scope</tt> argument to #define_callbacks.
|
644
747
|
#
|
645
748
|
# If a proc, lambda, or block is given, its body is evaluated in the context
|
646
749
|
# of the current object. It can also optionally accept the current object as
|
@@ -684,14 +787,39 @@ module ActiveSupport
|
|
684
787
|
end
|
685
788
|
end
|
686
789
|
|
687
|
-
# Skip a previously set callback. Like
|
790
|
+
# Skip a previously set callback. Like #set_callback, <tt>:if</tt> or
|
688
791
|
# <tt>:unless</tt> options may be passed in order to control when the
|
689
792
|
# callback is skipped.
|
690
793
|
#
|
691
|
-
#
|
692
|
-
#
|
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 }
|
693
800
|
# end
|
694
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
|
+
#
|
695
823
|
# An <tt>ArgumentError</tt> will be raised if the callback has not
|
696
824
|
# already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
|
697
825
|
def skip_callback(name, *filter_list, &block)
|
@@ -722,7 +850,7 @@ module ActiveSupport
|
|
722
850
|
def reset_callbacks(name)
|
723
851
|
callbacks = get_callbacks name
|
724
852
|
|
725
|
-
|
853
|
+
self.descendants.each do |target|
|
726
854
|
chain = target.get_callbacks(name).dup
|
727
855
|
callbacks.each { |c| chain.delete(c) }
|
728
856
|
target.set_callbacks name, chain
|
@@ -808,14 +936,14 @@ module ActiveSupport
|
|
808
936
|
# <tt>!</tt>, <tt>?</tt> or <tt>=</tt>.
|
809
937
|
#
|
810
938
|
# Calling +define_callbacks+ multiple times with the same +names+ will
|
811
|
-
# overwrite previous callbacks registered with
|
939
|
+
# overwrite previous callbacks registered with #set_callback.
|
812
940
|
def define_callbacks(*names)
|
813
941
|
options = names.extract_options!
|
814
942
|
|
815
943
|
names.each do |name|
|
816
944
|
name = name.to_sym
|
817
945
|
|
818
|
-
([self] +
|
946
|
+
([self] + self.descendants).each do |target|
|
819
947
|
target.set_callbacks name, CallbackChain.new(name, options)
|
820
948
|
end
|
821
949
|
|
@@ -844,18 +972,12 @@ module ActiveSupport
|
|
844
972
|
__callbacks[name.to_sym]
|
845
973
|
end
|
846
974
|
|
847
|
-
|
848
|
-
|
849
|
-
self.__callbacks = __callbacks.
|
850
|
-
end
|
851
|
-
else # Ruby 2.6 and newer
|
852
|
-
def set_callbacks(name, callbacks) # :nodoc:
|
853
|
-
unless singleton_class.method_defined?(:__callbacks, false)
|
854
|
-
self.__callbacks = __callbacks.dup
|
855
|
-
end
|
856
|
-
self.__callbacks[name.to_sym] = callbacks
|
857
|
-
self.__callbacks
|
975
|
+
def set_callbacks(name, callbacks) # :nodoc:
|
976
|
+
unless singleton_class.method_defined?(:__callbacks, false)
|
977
|
+
self.__callbacks = __callbacks.dup
|
858
978
|
end
|
979
|
+
self.__callbacks[name.to_sym] = callbacks
|
980
|
+
self.__callbacks
|
859
981
|
end
|
860
982
|
end
|
861
983
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
class CodeGenerator # :nodoc:
|
5
|
+
class MethodSet
|
6
|
+
METHOD_CACHES = Hash.new { |h, k| h[k] = Module.new }
|
7
|
+
|
8
|
+
def initialize(namespace)
|
9
|
+
@cache = METHOD_CACHES[namespace]
|
10
|
+
@sources = []
|
11
|
+
@methods = {}
|
12
|
+
@canonical_methods = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def define_cached_method(canonical_name, as: nil)
|
16
|
+
canonical_name = canonical_name.to_sym
|
17
|
+
as = (as || canonical_name).to_sym
|
18
|
+
|
19
|
+
@methods.fetch(as) do
|
20
|
+
unless @cache.method_defined?(canonical_name) || @canonical_methods[canonical_name]
|
21
|
+
yield @sources
|
22
|
+
end
|
23
|
+
@canonical_methods[canonical_name] = true
|
24
|
+
@methods[as] = canonical_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def apply(owner, path, line)
|
29
|
+
unless @sources.empty?
|
30
|
+
@cache.module_eval("# frozen_string_literal: true\n" + @sources.join(";"), path, line)
|
31
|
+
end
|
32
|
+
@canonical_methods.clear
|
33
|
+
|
34
|
+
@methods.each do |as, canonical_name|
|
35
|
+
owner.define_method(as, @cache.instance_method(canonical_name))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
def batch(owner, path, line)
|
42
|
+
if owner.is_a?(CodeGenerator)
|
43
|
+
yield owner
|
44
|
+
else
|
45
|
+
instance = new(owner, path, line)
|
46
|
+
result = yield instance
|
47
|
+
instance.execute
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(owner, path, line)
|
54
|
+
@owner = owner
|
55
|
+
@path = path
|
56
|
+
@line = line
|
57
|
+
@namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def define_cached_method(canonical_name, namespace:, as: nil, &block)
|
61
|
+
@namespaces[namespace].define_cached_method(canonical_name, as: as, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def execute
|
65
|
+
@namespaces.each_value do |method_set|
|
66
|
+
method_set.apply(@owner, @path, @line - 1)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
|
+
# = Active Support \Concern
|
5
|
+
#
|
4
6
|
# A typical module looks like this:
|
5
7
|
#
|
6
8
|
# module M
|
@@ -16,7 +18,7 @@ module ActiveSupport
|
|
16
18
|
# end
|
17
19
|
# end
|
18
20
|
#
|
19
|
-
# By using
|
21
|
+
# By using +ActiveSupport::Concern+ the above module could instead be
|
20
22
|
# written as:
|
21
23
|
#
|
22
24
|
# require "active_support/concern"
|
@@ -73,7 +75,7 @@ module ActiveSupport
|
|
73
75
|
# end
|
74
76
|
#
|
75
77
|
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
|
76
|
-
# is the +Bar+ module, not the +Host+ class. With
|
78
|
+
# is the +Bar+ module, not the +Host+ class. With +ActiveSupport::Concern+,
|
77
79
|
# module dependencies are properly resolved:
|
78
80
|
#
|
79
81
|
# require "active_support/concern"
|
@@ -108,23 +110,23 @@ module ActiveSupport
|
|
108
110
|
#
|
109
111
|
# <tt>prepend</tt> is also used for any dependencies.
|
110
112
|
module Concern
|
111
|
-
class MultipleIncludedBlocks < StandardError
|
113
|
+
class MultipleIncludedBlocks < StandardError # :nodoc:
|
112
114
|
def initialize
|
113
115
|
super "Cannot define multiple 'included' blocks for a Concern"
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
117
|
-
class MultiplePrependBlocks < StandardError
|
119
|
+
class MultiplePrependBlocks < StandardError # :nodoc:
|
118
120
|
def initialize
|
119
121
|
super "Cannot define multiple 'prepended' blocks for a Concern"
|
120
122
|
end
|
121
123
|
end
|
122
124
|
|
123
|
-
def self.extended(base)
|
125
|
+
def self.extended(base) # :nodoc:
|
124
126
|
base.instance_variable_set(:@_dependencies, [])
|
125
127
|
end
|
126
128
|
|
127
|
-
def append_features(base)
|
129
|
+
def append_features(base) # :nodoc:
|
128
130
|
if base.instance_variable_defined?(:@_dependencies)
|
129
131
|
base.instance_variable_get(:@_dependencies) << self
|
130
132
|
false
|
@@ -137,7 +139,7 @@ module ActiveSupport
|
|
137
139
|
end
|
138
140
|
end
|
139
141
|
|
140
|
-
def prepend_features(base)
|
142
|
+
def prepend_features(base) # :nodoc:
|
141
143
|
if base.instance_variable_defined?(:@_dependencies)
|
142
144
|
base.instance_variable_get(:@_dependencies).unshift self
|
143
145
|
false
|