activesupport 6.1.6.1 → 7.0.3.1
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 +231 -515
- 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 +132 -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 +47 -72
- data/lib/active_support/cache/strategy/local_cache.rb +38 -61
- data/lib/active_support/cache.rb +193 -46
- 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 +9 -9
- data/lib/active_support/core_ext/date/conversions.rb +14 -14
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -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/conversions.rb +13 -13
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -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 +101 -32
- 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/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +1 -1
- 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 +11 -0
- data/lib/active_support/core_ext/object/json.rb +30 -25
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with_options.rb +20 -1
- 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 +26 -0
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -25
- 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 -1
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +62 -38
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/time/calculations.rb +7 -8
- data/lib/active_support/core_ext/time/conversions.rb +13 -12
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +7 -22
- 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 -14
- 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 +5 -2
- 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 +13 -2
- data/lib/active_support/encrypted_file.rb +1 -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 +3 -5
- 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 +24 -48
- 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 +14 -3
- 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.rb +4 -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 +17 -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 +0 -2
- data/lib/active_support/option_merger.rb +8 -16
- 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 +5 -0
- data/lib/active_support/per_thread_registry.rb +5 -1
- data/lib/active_support/railtie.rb +69 -19
- data/lib/active_support/rescuable.rb +4 -4
- 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 +16 -1
- data/lib/active_support/test_case.rb +9 -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 +2 -2
- 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 +58 -17
- 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 +23 -21
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
@@ -5,6 +5,7 @@ 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
|
@@ -15,19 +16,19 @@ module ActiveSupport
|
|
15
16
|
# needing to override or redefine methods of the base class.
|
16
17
|
#
|
17
18
|
# Mixing in this module allows you to define the events in the object's
|
18
|
-
# life cycle that will support callbacks (via
|
19
|
+
# life cycle that will support callbacks (via ClassMethods#define_callbacks),
|
19
20
|
# set the instance methods, procs, or callback objects to be called (via
|
20
|
-
#
|
21
|
+
# ClassMethods#set_callback), and run the installed callbacks at the
|
21
22
|
# appropriate times (via +run_callbacks+).
|
22
23
|
#
|
23
24
|
# By default callbacks are halted by throwing +:abort+.
|
24
|
-
# See
|
25
|
+
# See ClassMethods#define_callbacks for details.
|
25
26
|
#
|
26
27
|
# Three kinds of callbacks are supported: before callbacks, run before a
|
27
28
|
# certain event; after callbacks, run after the event; and around callbacks,
|
28
29
|
# blocks that surround the event, triggering it when they yield. Callback code
|
29
30
|
# can be contained in instance methods, procs or lambdas, or callback objects
|
30
|
-
# that respond to certain predetermined methods. See
|
31
|
+
# that respond to certain predetermined methods. See ClassMethods#set_callback
|
31
32
|
# for details.
|
32
33
|
#
|
33
34
|
# class Record
|
@@ -276,7 +277,7 @@ module ActiveSupport
|
|
276
277
|
end
|
277
278
|
end
|
278
279
|
|
279
|
-
class Callback
|
280
|
+
class Callback # :nodoc:#
|
280
281
|
def self.build(chain, filter, kind, options)
|
281
282
|
if filter.is_a?(String)
|
282
283
|
raise ArgumentError, <<-MSG.squish
|
@@ -289,21 +290,17 @@ module ActiveSupport
|
|
289
290
|
end
|
290
291
|
|
291
292
|
attr_accessor :kind, :name
|
292
|
-
attr_reader :chain_config
|
293
|
+
attr_reader :chain_config, :filter
|
293
294
|
|
294
295
|
def initialize(name, filter, kind, options, chain_config)
|
295
296
|
@chain_config = chain_config
|
296
297
|
@name = name
|
297
298
|
@kind = kind
|
298
299
|
@filter = filter
|
299
|
-
@key = compute_identifier filter
|
300
300
|
@if = check_conditionals(options[:if])
|
301
301
|
@unless = check_conditionals(options[:unless])
|
302
302
|
end
|
303
303
|
|
304
|
-
def filter; @key; end
|
305
|
-
def raw_filter; @filter; end
|
306
|
-
|
307
304
|
def merge_conditional_options(chain, if_option:, unless_option:)
|
308
305
|
options = {
|
309
306
|
if: @if.dup,
|
@@ -356,7 +353,7 @@ module ActiveSupport
|
|
356
353
|
return EMPTY_ARRAY if conditionals.blank?
|
357
354
|
|
358
355
|
conditionals = Array(conditionals)
|
359
|
-
if conditionals.any?
|
356
|
+
if conditionals.any?(String)
|
360
357
|
raise ArgumentError, <<-MSG.squish
|
361
358
|
Passing string to be evaluated in :if and :unless conditional
|
362
359
|
options is not supported. Pass a symbol for an instance method,
|
@@ -367,15 +364,6 @@ module ActiveSupport
|
|
367
364
|
conditionals.freeze
|
368
365
|
end
|
369
366
|
|
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
367
|
def conditions_lambdas
|
380
368
|
@if.map { |c| CallTemplate.build(c, self).make_lambda } +
|
381
369
|
@unless.map { |c| CallTemplate.build(c, self).inverted_lambda }
|
@@ -384,56 +372,153 @@ module ActiveSupport
|
|
384
372
|
|
385
373
|
# A future invocation of user-supplied code (either as a callback,
|
386
374
|
# or a condition filter).
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
375
|
+
module CallTemplate # :nodoc:
|
376
|
+
class MethodCall
|
377
|
+
def initialize(method)
|
378
|
+
@method_name = method
|
379
|
+
end
|
380
|
+
|
381
|
+
# Return the parts needed to make this call, with the given
|
382
|
+
# input values.
|
383
|
+
#
|
384
|
+
# Returns an array of the form:
|
385
|
+
#
|
386
|
+
# [target, block, method, *arguments]
|
387
|
+
#
|
388
|
+
# This array can be used as such:
|
389
|
+
#
|
390
|
+
# target.send(method, *arguments, &block)
|
391
|
+
#
|
392
|
+
# The actual invocation is left up to the caller to minimize
|
393
|
+
# call stack pollution.
|
394
|
+
def expand(target, value, block)
|
395
|
+
[target, block, @method_name]
|
396
|
+
end
|
397
|
+
|
398
|
+
def make_lambda
|
399
|
+
lambda do |target, value, &block|
|
400
|
+
target.send(@method_name, &block)
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def inverted_lambda
|
405
|
+
lambda do |target, value, &block|
|
406
|
+
!target.send(@method_name, &block)
|
407
|
+
end
|
408
|
+
end
|
393
409
|
end
|
394
410
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
# target.send(method, *arguments, &block)
|
405
|
-
#
|
406
|
-
# The actual invocation is left up to the caller to minimize
|
407
|
-
# call stack pollution.
|
408
|
-
def expand(target, value, block)
|
409
|
-
expanded = [@override_target || target, @override_block || block, @method_name]
|
411
|
+
class ObjectCall
|
412
|
+
def initialize(target, method)
|
413
|
+
@override_target = target
|
414
|
+
@method_name = method
|
415
|
+
end
|
416
|
+
|
417
|
+
def expand(target, value, block)
|
418
|
+
[@override_target || target, block, @method_name, target]
|
419
|
+
end
|
410
420
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
when :target then expanded << target
|
415
|
-
when :block then expanded << (block || raise(ArgumentError))
|
421
|
+
def make_lambda
|
422
|
+
lambda do |target, value, &block|
|
423
|
+
(@override_target || target).send(@method_name, target, &block)
|
416
424
|
end
|
417
425
|
end
|
418
426
|
|
419
|
-
|
427
|
+
def inverted_lambda
|
428
|
+
lambda do |target, value, &block|
|
429
|
+
!(@override_target || target).send(@method_name, target, &block)
|
430
|
+
end
|
431
|
+
end
|
420
432
|
end
|
421
433
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
434
|
+
class InstanceExec0
|
435
|
+
def initialize(block)
|
436
|
+
@override_block = block
|
437
|
+
end
|
438
|
+
|
439
|
+
def expand(target, value, block)
|
440
|
+
[target, @override_block, :instance_exec]
|
441
|
+
end
|
442
|
+
|
443
|
+
def make_lambda
|
444
|
+
lambda do |target, value, &block|
|
445
|
+
target.instance_exec(&@override_block)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
def inverted_lambda
|
450
|
+
lambda do |target, value, &block|
|
451
|
+
!target.instance_exec(&@override_block)
|
452
|
+
end
|
428
453
|
end
|
429
454
|
end
|
430
455
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
456
|
+
class InstanceExec1
|
457
|
+
def initialize(block)
|
458
|
+
@override_block = block
|
459
|
+
end
|
460
|
+
|
461
|
+
def expand(target, value, block)
|
462
|
+
[target, @override_block, :instance_exec, target]
|
463
|
+
end
|
464
|
+
|
465
|
+
def make_lambda
|
466
|
+
lambda do |target, value, &block|
|
467
|
+
target.instance_exec(target, &@override_block)
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
def inverted_lambda
|
472
|
+
lambda do |target, value, &block|
|
473
|
+
!target.instance_exec(target, &@override_block)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
class InstanceExec2
|
479
|
+
def initialize(block)
|
480
|
+
@override_block = block
|
481
|
+
end
|
482
|
+
|
483
|
+
def expand(target, value, block)
|
484
|
+
raise ArgumentError unless block
|
485
|
+
[target, @override_block || block, :instance_exec, target, block]
|
486
|
+
end
|
487
|
+
|
488
|
+
def make_lambda
|
489
|
+
lambda do |target, value, &block|
|
490
|
+
raise ArgumentError unless block
|
491
|
+
target.instance_exec(target, block, &@override_block)
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
def inverted_lambda
|
496
|
+
lambda do |target, value, &block|
|
497
|
+
raise ArgumentError unless block
|
498
|
+
!target.instance_exec(target, block, &@override_block)
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
class ProcCall
|
504
|
+
def initialize(target)
|
505
|
+
@override_target = target
|
506
|
+
end
|
507
|
+
|
508
|
+
def expand(target, value, block)
|
509
|
+
[@override_target || target, block, :call, target, value]
|
510
|
+
end
|
511
|
+
|
512
|
+
def make_lambda
|
513
|
+
lambda do |target, value, &block|
|
514
|
+
(@override_target || target).call(target, value, &block)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def inverted_lambda
|
519
|
+
lambda do |target, value, &block|
|
520
|
+
!(@override_target || target).call(target, value, &block)
|
521
|
+
end
|
437
522
|
end
|
438
523
|
end
|
439
524
|
|
@@ -448,21 +533,19 @@ module ActiveSupport
|
|
448
533
|
def self.build(filter, callback)
|
449
534
|
case filter
|
450
535
|
when Symbol
|
451
|
-
new(
|
536
|
+
MethodCall.new(filter)
|
452
537
|
when Conditionals::Value
|
453
|
-
new(filter
|
538
|
+
ProcCall.new(filter)
|
454
539
|
when ::Proc
|
455
540
|
if filter.arity > 1
|
456
|
-
new(
|
541
|
+
InstanceExec2.new(filter)
|
457
542
|
elsif filter.arity > 0
|
458
|
-
new(
|
543
|
+
InstanceExec1.new(filter)
|
459
544
|
else
|
460
|
-
new(
|
545
|
+
InstanceExec0.new(filter)
|
461
546
|
end
|
462
547
|
else
|
463
|
-
|
464
|
-
|
465
|
-
new(filter, method_to_call, [:target], nil)
|
548
|
+
ObjectCall.new(filter, callback.current_scopes.join("_").to_sym)
|
466
549
|
end
|
467
550
|
end
|
468
551
|
end
|
@@ -517,7 +600,7 @@ module ActiveSupport
|
|
517
600
|
end
|
518
601
|
end
|
519
602
|
|
520
|
-
class CallbackChain
|
603
|
+
class CallbackChain # :nodoc:
|
521
604
|
include Enumerable
|
522
605
|
|
523
606
|
attr_reader :name, :config
|
@@ -619,8 +702,8 @@ module ActiveSupport
|
|
619
702
|
|
620
703
|
# This is used internally to append, prepend and skip callbacks to the
|
621
704
|
# CallbackChain.
|
622
|
-
def __update_callbacks(name)
|
623
|
-
([self] +
|
705
|
+
def __update_callbacks(name) # :nodoc:
|
706
|
+
([self] + self.descendants).reverse_each do |target|
|
624
707
|
chain = target.get_callbacks name
|
625
708
|
yield target, chain.dup
|
626
709
|
end
|
@@ -688,10 +771,32 @@ module ActiveSupport
|
|
688
771
|
# <tt>:unless</tt> options may be passed in order to control when the
|
689
772
|
# callback is skipped.
|
690
773
|
#
|
691
|
-
# class Writer <
|
692
|
-
#
|
774
|
+
# class Writer < PersonRecord
|
775
|
+
# attr_accessor :age
|
776
|
+
# skip_callback :save, :before, :saving_message, if: -> { age > 18 }
|
693
777
|
# end
|
694
778
|
#
|
779
|
+
# When if option returns true, callback is skipped.
|
780
|
+
#
|
781
|
+
# writer = Writer.new
|
782
|
+
# writer.age = 20
|
783
|
+
# writer.save
|
784
|
+
#
|
785
|
+
# Output:
|
786
|
+
# - save
|
787
|
+
# saved
|
788
|
+
#
|
789
|
+
# When if option returns false, callback is NOT skipped.
|
790
|
+
#
|
791
|
+
# young_writer = Writer.new
|
792
|
+
# young_writer.age = 17
|
793
|
+
# young_writer.save
|
794
|
+
#
|
795
|
+
# Output:
|
796
|
+
# saving...
|
797
|
+
# - save
|
798
|
+
# saved
|
799
|
+
#
|
695
800
|
# An <tt>ArgumentError</tt> will be raised if the callback has not
|
696
801
|
# already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
|
697
802
|
def skip_callback(name, *filter_list, &block)
|
@@ -722,7 +827,7 @@ module ActiveSupport
|
|
722
827
|
def reset_callbacks(name)
|
723
828
|
callbacks = get_callbacks name
|
724
829
|
|
725
|
-
|
830
|
+
self.descendants.each do |target|
|
726
831
|
chain = target.get_callbacks(name).dup
|
727
832
|
callbacks.each { |c| chain.delete(c) }
|
728
833
|
target.set_callbacks name, chain
|
@@ -815,7 +920,7 @@ module ActiveSupport
|
|
815
920
|
names.each do |name|
|
816
921
|
name = name.to_sym
|
817
922
|
|
818
|
-
([self] +
|
923
|
+
([self] + self.descendants).each do |target|
|
819
924
|
target.set_callbacks name, CallbackChain.new(name, options)
|
820
925
|
end
|
821
926
|
|
@@ -844,18 +949,12 @@ module ActiveSupport
|
|
844
949
|
__callbacks[name.to_sym]
|
845
950
|
end
|
846
951
|
|
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
|
952
|
+
def set_callbacks(name, callbacks) # :nodoc:
|
953
|
+
unless singleton_class.method_defined?(:__callbacks, false)
|
954
|
+
self.__callbacks = __callbacks.dup
|
858
955
|
end
|
956
|
+
self.__callbacks[name.to_sym] = callbacks
|
957
|
+
self.__callbacks
|
859
958
|
end
|
860
959
|
end
|
861
960
|
end
|
@@ -0,0 +1,65 @@
|
|
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
|
+
end
|
13
|
+
|
14
|
+
def define_cached_method(name, as: name)
|
15
|
+
name = name.to_sym
|
16
|
+
as = as.to_sym
|
17
|
+
@methods.fetch(name) do
|
18
|
+
unless @cache.method_defined?(as)
|
19
|
+
yield @sources
|
20
|
+
end
|
21
|
+
@methods[name] = as
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def apply(owner, path, line)
|
26
|
+
unless @sources.empty?
|
27
|
+
@cache.module_eval("# frozen_string_literal: true\n" + @sources.join(";"), path, line)
|
28
|
+
end
|
29
|
+
@methods.each do |name, as|
|
30
|
+
owner.define_method(name, @cache.instance_method(as))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
def batch(owner, path, line)
|
37
|
+
if owner.is_a?(CodeGenerator)
|
38
|
+
yield owner
|
39
|
+
else
|
40
|
+
instance = new(owner, path, line)
|
41
|
+
result = yield instance
|
42
|
+
instance.execute
|
43
|
+
result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(owner, path, line)
|
49
|
+
@owner = owner
|
50
|
+
@path = path
|
51
|
+
@line = line
|
52
|
+
@namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def define_cached_method(name, namespace:, as: name, &block)
|
56
|
+
@namespaces[namespace].define_cached_method(name, as: as, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def execute
|
60
|
+
@namespaces.each_value do |method_set|
|
61
|
+
method_set.apply(@owner, @path, @line - 1)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -108,23 +108,23 @@ module ActiveSupport
|
|
108
108
|
#
|
109
109
|
# <tt>prepend</tt> is also used for any dependencies.
|
110
110
|
module Concern
|
111
|
-
class MultipleIncludedBlocks < StandardError
|
111
|
+
class MultipleIncludedBlocks < StandardError # :nodoc:
|
112
112
|
def initialize
|
113
113
|
super "Cannot define multiple 'included' blocks for a Concern"
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
-
class MultiplePrependBlocks < StandardError
|
117
|
+
class MultiplePrependBlocks < StandardError # :nodoc:
|
118
118
|
def initialize
|
119
119
|
super "Cannot define multiple 'prepended' blocks for a Concern"
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
def self.extended(base)
|
123
|
+
def self.extended(base) # :nodoc:
|
124
124
|
base.instance_variable_set(:@_dependencies, [])
|
125
125
|
end
|
126
126
|
|
127
|
-
def append_features(base)
|
127
|
+
def append_features(base) # :nodoc:
|
128
128
|
if base.instance_variable_defined?(:@_dependencies)
|
129
129
|
base.instance_variable_get(:@_dependencies) << self
|
130
130
|
false
|
@@ -137,7 +137,7 @@ module ActiveSupport
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
def prepend_features(base)
|
140
|
+
def prepend_features(base) # :nodoc:
|
141
141
|
if base.instance_variable_defined?(:@_dependencies)
|
142
142
|
base.instance_variable_get(:@_dependencies).unshift self
|
143
143
|
false
|
@@ -17,14 +17,12 @@ module ActiveSupport
|
|
17
17
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super }
|
18
18
|
end
|
19
19
|
|
20
|
-
def synchronize
|
20
|
+
def synchronize(&block)
|
21
21
|
Thread.handle_interrupt(EXCEPTION_NEVER) do
|
22
22
|
mon_enter
|
23
23
|
|
24
24
|
begin
|
25
|
-
Thread.handle_interrupt(EXCEPTION_IMMEDIATE)
|
26
|
-
yield
|
27
|
-
end
|
25
|
+
Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
|
28
26
|
ensure
|
29
27
|
mon_exit
|
30
28
|
end
|
@@ -215,9 +215,9 @@ module ActiveSupport
|
|
215
215
|
@waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
|
216
216
|
end
|
217
217
|
|
218
|
-
def wait_for(method)
|
218
|
+
def wait_for(method, &block)
|
219
219
|
@sleeping[Thread.current] = method
|
220
|
-
@cv.wait_while
|
220
|
+
@cv.wait_while(&block)
|
221
221
|
ensure
|
222
222
|
@sleeping.delete Thread.current
|
223
223
|
end
|
@@ -5,7 +5,7 @@ require "active_support/ordered_options"
|
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
7
|
# Configurable provides a <tt>config</tt> method to store and retrieve
|
8
|
-
# configuration options as an
|
8
|
+
# configuration options as an OrderedOptions.
|
9
9
|
module Configurable
|
10
10
|
extend ActiveSupport::Concern
|
11
11
|
|
@@ -94,17 +94,19 @@ module ActiveSupport
|
|
94
94
|
# User.new.allowed_access = true # => NoMethodError
|
95
95
|
# User.new.allowed_access # => NoMethodError
|
96
96
|
#
|
97
|
-
# Also you can pass a block to set up the attribute with a default value.
|
97
|
+
# Also you can pass <tt>default</tt> or a block to set up the attribute with a default value.
|
98
98
|
#
|
99
99
|
# class User
|
100
100
|
# include ActiveSupport::Configurable
|
101
|
+
# config_accessor :allowed_access, default: false
|
101
102
|
# config_accessor :hair_colors do
|
102
103
|
# [:brown, :black, :blonde, :red]
|
103
104
|
# end
|
104
105
|
# end
|
105
106
|
#
|
107
|
+
# User.allowed_access # => false
|
106
108
|
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
107
|
-
def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
|
109
|
+
def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) # :doc:
|
108
110
|
names.each do |name|
|
109
111
|
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
|
110
112
|
|
@@ -118,13 +120,14 @@ module ActiveSupport
|
|
118
120
|
class_eval reader, __FILE__, reader_line if instance_reader
|
119
121
|
class_eval writer, __FILE__, writer_line if instance_writer
|
120
122
|
end
|
121
|
-
|
123
|
+
|
124
|
+
send("#{name}=", block_given? ? yield : default)
|
122
125
|
end
|
123
126
|
end
|
124
127
|
private :config_accessor
|
125
128
|
end
|
126
129
|
|
127
|
-
# Reads and writes attributes from a configuration
|
130
|
+
# Reads and writes attributes from a configuration OrderedOptions.
|
128
131
|
#
|
129
132
|
# require "active_support/configurable"
|
130
133
|
#
|
@@ -38,7 +38,7 @@ module ActiveSupport
|
|
38
38
|
|
39
39
|
File.read(content_path).tap do |content|
|
40
40
|
if content.include?("\u00A0")
|
41
|
-
warn "
|
41
|
+
warn "#{content_path} contains invisible non-breaking spaces, you may want to remove those"
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/xml_mini"
|
4
3
|
require "active_support/core_ext/hash/keys"
|
5
4
|
require "active_support/core_ext/string/inflections"
|
6
5
|
require "active_support/core_ext/object/to_param"
|
@@ -16,12 +15,12 @@ class Array
|
|
16
15
|
#
|
17
16
|
# ==== Options
|
18
17
|
#
|
19
|
-
# * <tt>:words_connector</tt> - The sign or word used to join the
|
20
|
-
# in arrays with
|
21
|
-
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements
|
22
|
-
# in arrays with two elements (default: " and ").
|
18
|
+
# * <tt>:words_connector</tt> - The sign or word used to join all but the last
|
19
|
+
# element in arrays with three or more elements (default: ", ").
|
23
20
|
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element
|
24
21
|
# in arrays with three or more elements (default: ", and ").
|
22
|
+
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements
|
23
|
+
# in arrays with two elements (default: " and ").
|
25
24
|
# * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
|
26
25
|
# the connector options defined on the 'support.array' namespace in the
|
27
26
|
# corresponding dictionary file.
|
@@ -66,7 +65,7 @@ class Array
|
|
66
65
|
two_words_connector: " and ",
|
67
66
|
last_word_connector: ", and "
|
68
67
|
}
|
69
|
-
if defined?(I18n)
|
68
|
+
if options[:locale] != false && defined?(I18n)
|
70
69
|
i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
|
71
70
|
default_connectors.merge!(i18n_connectors)
|
72
71
|
end
|
@@ -87,10 +86,12 @@ class Array
|
|
87
86
|
# Extends <tt>Array#to_s</tt> to convert a collection of elements into a
|
88
87
|
# comma separated id list if <tt>:db</tt> argument is given as the format.
|
89
88
|
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
|
89
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
90
|
+
#
|
91
|
+
# Blog.all.to_fs(:db) # => "1,2,3"
|
92
|
+
# Blog.none.to_fs(:db) # => "null"
|
93
|
+
# [1,2].to_fs # => "[1, 2]"
|
94
|
+
def to_fs(format = :default)
|
94
95
|
case format
|
95
96
|
when :db
|
96
97
|
if empty?
|
@@ -102,8 +103,8 @@ class Array
|
|
102
103
|
to_default_s
|
103
104
|
end
|
104
105
|
end
|
106
|
+
alias_method :to_formatted_s, :to_fs
|
105
107
|
alias_method :to_default_s, :to_s
|
106
|
-
alias_method :to_s, :to_formatted_s
|
107
108
|
|
108
109
|
# Returns a string that represents the array in XML by invoking +to_xml+
|
109
110
|
# on each element. Active Record collections delegate their representation
|
@@ -187,7 +188,7 @@ class Array
|
|
187
188
|
options[:indent] ||= 2
|
188
189
|
options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
|
189
190
|
options[:root] ||= \
|
190
|
-
if first.class != Hash && all?
|
191
|
+
if first.class != Hash && all?(first.class)
|
191
192
|
underscored = ActiveSupport::Inflector.underscore(first.class.name)
|
192
193
|
ActiveSupport::Inflector.pluralize(underscored).tr("/", "_")
|
193
194
|
else
|