activesupport 6.0.6.1 → 6.1.0.rc1
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 +337 -573
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +3 -3
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +2 -2
- data/lib/active_support/cache/mem_cache_store.rb +20 -14
- data/lib/active_support/cache/memory_store.rb +38 -26
- data/lib/active_support/cache/redis_cache_store.rb +25 -25
- data/lib/active_support/cache/strategy/local_cache.rb +13 -4
- data/lib/active_support/cache.rb +75 -34
- data/lib/active_support/callbacks.rb +65 -56
- data/lib/active_support/concern.rb +46 -2
- data/lib/active_support/configurable.rb +3 -3
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +17 -38
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/enumerable.rb +76 -4
- data/lib/active_support/core_ext/hash/conversions.rb +2 -2
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +1 -1
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/marshal.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +38 -28
- data/lib/active_support/core_ext/module/introspection.rb +1 -25
- data/lib/active_support/core_ext/name_error.rb +29 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +5 -1
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/range/compare_range.rb +9 -3
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/inflections.rb +38 -4
- data/lib/active_support/core_ext/string/inquiry.rb +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +8 -38
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +5 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +7 -2
- data/lib/active_support/dependencies.rb +38 -24
- data/lib/active_support/deprecation/behaviors.rb +15 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +0 -1
- data/lib/active_support/deprecation/method_wrappers.rb +3 -2
- data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/descendants_tracker.rb +6 -2
- data/lib/active_support/duration/iso8601_serializer.rb +15 -9
- data/lib/active_support/duration.rb +71 -22
- data/lib/active_support/encrypted_file.rb +19 -2
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +69 -133
- data/lib/active_support/execution_wrapper.rb +13 -16
- data/lib/active_support/fork_tracker.rb +58 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +35 -22
- data/lib/active_support/i18n_railtie.rb +14 -19
- data/lib/active_support/inflector/inflections.rb +1 -2
- data/lib/active_support/inflector/methods.rb +35 -31
- data/lib/active_support/inflector/transliterate.rb +4 -4
- data/lib/active_support/json/decoding.rb +4 -4
- data/lib/active_support/json/encoding.rb +5 -1
- data/lib/active_support/key_generator.rb +1 -1
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber.rb +8 -0
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +34 -12
- data/lib/active_support/message_encryptor.rb +4 -7
- data/lib/active_support/message_verifier.rb +5 -5
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +6 -5
- data/lib/active_support/multibyte/chars.rb +4 -42
- data/lib/active_support/multibyte/unicode.rb +9 -83
- data/lib/active_support/notifications/fanout.rb +23 -8
- data/lib/active_support/notifications/instrumenter.rb +6 -15
- data/lib/active_support/notifications.rb +31 -4
- data/lib/active_support/number_helper/number_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 +1 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -3
- data/lib/active_support/number_helper/rounding_helper.rb +12 -28
- data/lib/active_support/number_helper.rb +29 -14
- data/lib/active_support/option_merger.rb +2 -1
- data/lib/active_support/ordered_options.rb +8 -2
- data/lib/active_support/parameter_filter.rb +15 -10
- data/lib/active_support/per_thread_registry.rb +1 -1
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +23 -1
- data/lib/active_support/reloader.rb +1 -1
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +4 -2
- data/lib/active_support/subscriber.rb +12 -7
- data/lib/active_support/tagged_logging.rb +29 -4
- data/lib/active_support/testing/assertions.rb +18 -11
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +12 -95
- data/lib/active_support/testing/time_helpers.rb +40 -3
- data/lib/active_support/time_with_zone.rb +66 -42
- data/lib/active_support/values/time_zone.rb +20 -10
- data/lib/active_support/xml_mini/rexml.rb +8 -1
- data/lib/active_support.rb +13 -1
- metadata +39 -42
- 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/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/cache.rb
CHANGED
@@ -3,10 +3,12 @@
|
|
3
3
|
require "zlib"
|
4
4
|
require "active_support/core_ext/array/extract_options"
|
5
5
|
require "active_support/core_ext/array/wrap"
|
6
|
+
require "active_support/core_ext/enumerable"
|
6
7
|
require "active_support/core_ext/module/attribute_accessors"
|
7
8
|
require "active_support/core_ext/numeric/bytes"
|
8
9
|
require "active_support/core_ext/numeric/time"
|
9
10
|
require "active_support/core_ext/object/to_param"
|
11
|
+
require "active_support/core_ext/object/try"
|
10
12
|
require "active_support/core_ext/string/inflections"
|
11
13
|
|
12
14
|
module ActiveSupport
|
@@ -20,7 +22,7 @@ module ActiveSupport
|
|
20
22
|
|
21
23
|
# These options mean something to all cache implementations. Individual cache
|
22
24
|
# implementations may support additional options.
|
23
|
-
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl]
|
25
|
+
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl, :coder]
|
24
26
|
|
25
27
|
module Strategy
|
26
28
|
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
@@ -79,7 +81,7 @@ module ActiveSupport
|
|
79
81
|
#
|
80
82
|
# The +key+ argument can also respond to +cache_key+ or +to_param+.
|
81
83
|
def expand_cache_key(key, namespace = nil)
|
82
|
-
expanded_cache_key =
|
84
|
+
expanded_cache_key = namespace ? +"#{namespace}/" : +""
|
83
85
|
|
84
86
|
if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
|
85
87
|
expanded_cache_key << "#{prefix}/"
|
@@ -156,6 +158,8 @@ module ActiveSupport
|
|
156
158
|
# threshold is configurable with the <tt>:compress_threshold</tt> option,
|
157
159
|
# specified in bytes.
|
158
160
|
class Store
|
161
|
+
DEFAULT_CODER = Marshal
|
162
|
+
|
159
163
|
cattr_accessor :logger, instance_writer: true
|
160
164
|
|
161
165
|
attr_reader :silence, :options
|
@@ -183,6 +187,7 @@ module ActiveSupport
|
|
183
187
|
# namespace for the cache.
|
184
188
|
def initialize(options = nil)
|
185
189
|
@options = options ? options.dup : {}
|
190
|
+
@coder = @options.delete(:coder) { self.class::DEFAULT_CODER } || NullCoder
|
186
191
|
end
|
187
192
|
|
188
193
|
# Silences the logger.
|
@@ -441,8 +446,8 @@ module ActiveSupport
|
|
441
446
|
instrument :read_multi, names, options do |payload|
|
442
447
|
reads = read_multi_entries(names, **options)
|
443
448
|
writes = {}
|
444
|
-
ordered = names.
|
445
|
-
|
449
|
+
ordered = names.index_with do |name|
|
450
|
+
reads.fetch(name) { writes[name] = yield(name) }
|
446
451
|
end
|
447
452
|
|
448
453
|
payload[:hits] = reads.keys
|
@@ -477,6 +482,18 @@ module ActiveSupport
|
|
477
482
|
end
|
478
483
|
end
|
479
484
|
|
485
|
+
# Deletes multiple entries in the cache.
|
486
|
+
#
|
487
|
+
# Options are passed to the underlying cache implementation.
|
488
|
+
def delete_multi(names, options = nil)
|
489
|
+
options = merged_options(options)
|
490
|
+
names.map! { |key| normalize_key(key, options) }
|
491
|
+
|
492
|
+
instrument :delete_multi, names do
|
493
|
+
delete_multi_entries(names, **options)
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
480
497
|
# Returns +true+ if the cache contains an entry for the given key.
|
481
498
|
#
|
482
499
|
# Options are passed to the underlying cache implementation.
|
@@ -567,26 +584,31 @@ module ActiveSupport
|
|
567
584
|
raise NotImplementedError.new
|
568
585
|
end
|
569
586
|
|
587
|
+
def serialize_entry(entry)
|
588
|
+
@coder.dump(entry)
|
589
|
+
end
|
590
|
+
|
591
|
+
def deserialize_entry(payload)
|
592
|
+
payload.nil? ? nil : @coder.load(payload)
|
593
|
+
end
|
594
|
+
|
570
595
|
# Reads multiple entries from the cache implementation. Subclasses MAY
|
571
596
|
# implement this method.
|
572
597
|
def read_multi_entries(names, **options)
|
573
|
-
|
574
|
-
|
575
|
-
|
598
|
+
names.each_with_object({}) do |name, results|
|
599
|
+
key = normalize_key(name, options)
|
600
|
+
entry = read_entry(key, **options)
|
601
|
+
|
602
|
+
next unless entry
|
603
|
+
|
576
604
|
version = normalize_version(name, options)
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
elsif entry.mismatched?(version)
|
583
|
-
# Skip mismatched versions
|
584
|
-
else
|
585
|
-
results[name] = entry.value
|
586
|
-
end
|
605
|
+
|
606
|
+
if entry.expired?
|
607
|
+
delete_entry(key, **options)
|
608
|
+
elsif !entry.mismatched?(version)
|
609
|
+
results[name] = entry.value
|
587
610
|
end
|
588
611
|
end
|
589
|
-
results
|
590
612
|
end
|
591
613
|
|
592
614
|
# Writes multiple entries to the cache implementation. Subclasses MAY
|
@@ -603,6 +625,12 @@ module ActiveSupport
|
|
603
625
|
raise NotImplementedError.new
|
604
626
|
end
|
605
627
|
|
628
|
+
# Deletes multiples entries in the cache implementation. Subclasses MAY
|
629
|
+
# implement this method.
|
630
|
+
def delete_multi_entries(entries, **options)
|
631
|
+
entries.count { |key| delete_entry(key, **options) }
|
632
|
+
end
|
633
|
+
|
606
634
|
# Merges the default options with ones specific to a method call.
|
607
635
|
def merged_options(call_options)
|
608
636
|
if call_options
|
@@ -639,6 +667,10 @@ module ActiveSupport
|
|
639
667
|
namespace = namespace.call
|
640
668
|
end
|
641
669
|
|
670
|
+
if key && key.encoding != Encoding::UTF_8
|
671
|
+
key = key.dup.force_encoding(Encoding::UTF_8)
|
672
|
+
end
|
673
|
+
|
642
674
|
if namespace
|
643
675
|
"#{namespace}:#{key}"
|
644
676
|
else
|
@@ -655,15 +687,15 @@ module ActiveSupport
|
|
655
687
|
case key
|
656
688
|
when Array
|
657
689
|
if key.size > 1
|
658
|
-
key
|
690
|
+
key.collect { |element| expanded_key(element) }
|
659
691
|
else
|
660
|
-
|
692
|
+
expanded_key(key.first)
|
661
693
|
end
|
662
694
|
when Hash
|
663
|
-
key
|
664
|
-
|
665
|
-
|
666
|
-
|
695
|
+
key.collect { |k, v| "#{k}=#{v}" }.sort!
|
696
|
+
else
|
697
|
+
key
|
698
|
+
end.to_param
|
667
699
|
end
|
668
700
|
|
669
701
|
def normalize_version(key, options = nil)
|
@@ -673,24 +705,21 @@ module ActiveSupport
|
|
673
705
|
def expanded_version(key)
|
674
706
|
case
|
675
707
|
when key.respond_to?(:cache_version) then key.cache_version.to_param
|
676
|
-
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.compact.to_param
|
708
|
+
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.tap(&:compact!).to_param
|
677
709
|
when key.respond_to?(:to_a) then expanded_version(key.to_a)
|
678
710
|
end
|
679
711
|
end
|
680
712
|
|
681
713
|
def instrument(operation, key, options = nil)
|
682
|
-
|
714
|
+
if logger && logger.debug? && !silence?
|
715
|
+
logger.debug "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}"
|
716
|
+
end
|
683
717
|
|
684
|
-
payload = { key: key }
|
718
|
+
payload = { key: key, store: self.class.name }
|
685
719
|
payload.merge!(options) if options.is_a?(Hash)
|
686
720
|
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) { yield(payload) }
|
687
721
|
end
|
688
722
|
|
689
|
-
def log
|
690
|
-
return unless logger && logger.debug? && !silence?
|
691
|
-
logger.debug(yield)
|
692
|
-
end
|
693
|
-
|
694
723
|
def handle_expired_entry(entry, key, options)
|
695
724
|
if entry && entry.expired?
|
696
725
|
race_ttl = options[:race_condition_ttl].to_i
|
@@ -722,6 +751,18 @@ module ActiveSupport
|
|
722
751
|
end
|
723
752
|
end
|
724
753
|
|
754
|
+
module NullCoder # :nodoc:
|
755
|
+
class << self
|
756
|
+
def load(payload)
|
757
|
+
payload
|
758
|
+
end
|
759
|
+
|
760
|
+
def dump(entry)
|
761
|
+
entry
|
762
|
+
end
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
725
766
|
# This class is used to represent cache entries. Cache entries have a value, an optional
|
726
767
|
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
727
768
|
# on the cache. The version is used to support the :version option on the cache for rejecting
|
@@ -772,8 +813,8 @@ module ActiveSupport
|
|
772
813
|
end
|
773
814
|
|
774
815
|
# Returns the size of the cached value. This could be less than
|
775
|
-
# <tt>value.
|
776
|
-
def
|
816
|
+
# <tt>value.bytesize</tt> if the data is compressed.
|
817
|
+
def bytesize
|
777
818
|
case value
|
778
819
|
when NilClass
|
779
820
|
0
|
@@ -4,10 +4,7 @@ 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/deprecation"
|
11
8
|
require "thread"
|
12
9
|
|
13
10
|
module ActiveSupport
|
@@ -103,32 +100,6 @@ module ActiveSupport
|
|
103
100
|
env = Filters::Environment.new(self, false, nil)
|
104
101
|
next_sequence = callbacks.compile
|
105
102
|
|
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
|
131
|
-
|
132
103
|
# Common case: no 'around' callbacks defined
|
133
104
|
if next_sequence.final?
|
134
105
|
next_sequence.invoke_before(env)
|
@@ -136,6 +107,33 @@ module ActiveSupport
|
|
136
107
|
next_sequence.invoke_after(env)
|
137
108
|
env.value
|
138
109
|
else
|
110
|
+
invoke_sequence = Proc.new do
|
111
|
+
skipped = nil
|
112
|
+
|
113
|
+
while true
|
114
|
+
current = next_sequence
|
115
|
+
current.invoke_before(env)
|
116
|
+
if current.final?
|
117
|
+
env.value = !env.halted && (!block_given? || yield)
|
118
|
+
elsif current.skip?(env)
|
119
|
+
(skipped ||= []) << current
|
120
|
+
next_sequence = next_sequence.nested
|
121
|
+
next
|
122
|
+
else
|
123
|
+
next_sequence = next_sequence.nested
|
124
|
+
begin
|
125
|
+
target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
|
126
|
+
target.send(method, *arguments, &block)
|
127
|
+
ensure
|
128
|
+
next_sequence = current
|
129
|
+
end
|
130
|
+
end
|
131
|
+
current.invoke_after(env)
|
132
|
+
skipped.pop.invoke_after(env) while skipped&.first
|
133
|
+
break env.value
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
139
137
|
invoke_sequence.call
|
140
138
|
end
|
141
139
|
end
|
@@ -145,7 +143,7 @@ module ActiveSupport
|
|
145
143
|
# A hook invoked every time a before callback is halted.
|
146
144
|
# This can be overridden in ActiveSupport::Callbacks implementors in order
|
147
145
|
# to provide better debugging/logging.
|
148
|
-
def halted_callback_hook(filter)
|
146
|
+
def halted_callback_hook(filter, name)
|
149
147
|
end
|
150
148
|
|
151
149
|
module Conditionals # :nodoc:
|
@@ -161,17 +159,17 @@ module ActiveSupport
|
|
161
159
|
Environment = Struct.new(:target, :halted, :value)
|
162
160
|
|
163
161
|
class Before
|
164
|
-
def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter)
|
162
|
+
def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter, name)
|
165
163
|
halted_lambda = chain_config[:terminator]
|
166
164
|
|
167
165
|
if user_conditions.any?
|
168
|
-
halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
|
166
|
+
halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
|
169
167
|
else
|
170
|
-
halting(callback_sequence, user_callback, halted_lambda, filter)
|
168
|
+
halting(callback_sequence, user_callback, halted_lambda, filter, name)
|
171
169
|
end
|
172
170
|
end
|
173
171
|
|
174
|
-
def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter)
|
172
|
+
def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
|
175
173
|
callback_sequence.before do |env|
|
176
174
|
target = env.target
|
177
175
|
value = env.value
|
@@ -181,7 +179,7 @@ module ActiveSupport
|
|
181
179
|
result_lambda = -> { user_callback.call target, value }
|
182
180
|
env.halted = halted_lambda.call(target, result_lambda)
|
183
181
|
if env.halted
|
184
|
-
target.send :halted_callback_hook, filter
|
182
|
+
target.send :halted_callback_hook, filter, name
|
185
183
|
end
|
186
184
|
end
|
187
185
|
|
@@ -190,7 +188,7 @@ module ActiveSupport
|
|
190
188
|
end
|
191
189
|
private_class_method :halting_and_conditional
|
192
190
|
|
193
|
-
def self.halting(callback_sequence, user_callback, halted_lambda, filter)
|
191
|
+
def self.halting(callback_sequence, user_callback, halted_lambda, filter, name)
|
194
192
|
callback_sequence.before do |env|
|
195
193
|
target = env.target
|
196
194
|
value = env.value
|
@@ -199,9 +197,8 @@ module ActiveSupport
|
|
199
197
|
unless halted
|
200
198
|
result_lambda = -> { user_callback.call target, value }
|
201
199
|
env.halted = halted_lambda.call(target, result_lambda)
|
202
|
-
|
203
200
|
if env.halted
|
204
|
-
target.send :halted_callback_hook, filter
|
201
|
+
target.send :halted_callback_hook, filter, name
|
205
202
|
end
|
206
203
|
end
|
207
204
|
|
@@ -300,8 +297,8 @@ module ActiveSupport
|
|
300
297
|
@kind = kind
|
301
298
|
@filter = filter
|
302
299
|
@key = compute_identifier filter
|
303
|
-
@if = check_conditionals(
|
304
|
-
@unless = check_conditionals(
|
300
|
+
@if = check_conditionals(options[:if])
|
301
|
+
@unless = check_conditionals(options[:unless])
|
305
302
|
end
|
306
303
|
|
307
304
|
def filter; @key; end
|
@@ -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,7 +349,13 @@ 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
|
+
return EMPTY_ARRAY if conditionals.blank?
|
357
|
+
|
358
|
+
conditionals = Array(conditionals)
|
356
359
|
if conditionals.any? { |c| c.is_a?(String) }
|
357
360
|
raise ArgumentError, <<-MSG.squish
|
358
361
|
Passing string to be evaluated in :if and :unless conditional
|
@@ -361,7 +364,7 @@ module ActiveSupport
|
|
361
364
|
MSG
|
362
365
|
end
|
363
366
|
|
364
|
-
conditionals
|
367
|
+
conditionals.freeze
|
365
368
|
end
|
366
369
|
|
367
370
|
def compute_identifier(filter)
|
@@ -403,21 +406,17 @@ module ActiveSupport
|
|
403
406
|
# The actual invocation is left up to the caller to minimize
|
404
407
|
# call stack pollution.
|
405
408
|
def expand(target, value, block)
|
406
|
-
|
409
|
+
expanded = [@override_target || target, @override_block || block, @method_name]
|
410
|
+
|
411
|
+
@arguments.each do |arg|
|
407
412
|
case arg
|
408
|
-
when :value
|
409
|
-
when :target
|
410
|
-
when :block
|
413
|
+
when :value then expanded << value
|
414
|
+
when :target then expanded << target
|
415
|
+
when :block then expanded << (block || raise(ArgumentError))
|
411
416
|
end
|
412
|
-
|
413
|
-
|
414
|
-
result.unshift @method_name
|
415
|
-
result.unshift @override_block || block
|
416
|
-
result.unshift @override_target || target
|
417
|
+
end
|
417
418
|
|
418
|
-
|
419
|
-
# target.send(method, *arguments, &block)
|
420
|
-
result
|
419
|
+
expanded
|
421
420
|
end
|
422
421
|
|
423
422
|
# Return a lambda that will make this call when given the input
|
@@ -845,8 +844,18 @@ module ActiveSupport
|
|
845
844
|
__callbacks[name.to_sym]
|
846
845
|
end
|
847
846
|
|
848
|
-
|
849
|
-
|
847
|
+
if Module.instance_method(:method_defined?).arity == 1 # Ruby 2.5 and older
|
848
|
+
def set_callbacks(name, callbacks) # :nodoc:
|
849
|
+
self.__callbacks = __callbacks.merge(name.to_sym => 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
|
858
|
+
end
|
850
859
|
end
|
851
860
|
end
|
852
861
|
end
|
@@ -19,7 +19,7 @@ module ActiveSupport
|
|
19
19
|
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
20
20
|
# written as:
|
21
21
|
#
|
22
|
-
# require
|
22
|
+
# require "active_support/concern"
|
23
23
|
#
|
24
24
|
# module M
|
25
25
|
# extend ActiveSupport::Concern
|
@@ -76,7 +76,7 @@ module ActiveSupport
|
|
76
76
|
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
77
77
|
# module dependencies are properly resolved:
|
78
78
|
#
|
79
|
-
# require
|
79
|
+
# require "active_support/concern"
|
80
80
|
#
|
81
81
|
# module Foo
|
82
82
|
# extend ActiveSupport::Concern
|
@@ -99,6 +99,14 @@ module ActiveSupport
|
|
99
99
|
# class Host
|
100
100
|
# include Bar # It works, now Bar takes care of its dependencies
|
101
101
|
# end
|
102
|
+
#
|
103
|
+
# === Prepending concerns
|
104
|
+
#
|
105
|
+
# Just like `include`, concerns also support `prepend` with a corresponding
|
106
|
+
# `prepended do` callback. `module ClassMethods` or `class_methods do` are
|
107
|
+
# prepended as well.
|
108
|
+
#
|
109
|
+
# `prepend` is also used for any dependencies.
|
102
110
|
module Concern
|
103
111
|
class MultipleIncludedBlocks < StandardError #:nodoc:
|
104
112
|
def initialize
|
@@ -106,6 +114,12 @@ module ActiveSupport
|
|
106
114
|
end
|
107
115
|
end
|
108
116
|
|
117
|
+
class MultiplePrependBlocks < StandardError #:nodoc:
|
118
|
+
def initialize
|
119
|
+
super "Cannot define multiple 'prepended' blocks for a Concern"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
109
123
|
def self.extended(base) #:nodoc:
|
110
124
|
base.instance_variable_set(:@_dependencies, [])
|
111
125
|
end
|
@@ -123,6 +137,19 @@ module ActiveSupport
|
|
123
137
|
end
|
124
138
|
end
|
125
139
|
|
140
|
+
def prepend_features(base) #:nodoc:
|
141
|
+
if base.instance_variable_defined?(:@_dependencies)
|
142
|
+
base.instance_variable_get(:@_dependencies).unshift self
|
143
|
+
false
|
144
|
+
else
|
145
|
+
return false if base < self
|
146
|
+
@_dependencies.each { |dep| base.prepend(dep) }
|
147
|
+
super
|
148
|
+
base.singleton_class.prepend const_get(:ClassMethods) if const_defined?(:ClassMethods)
|
149
|
+
base.class_eval(&@_prepended_block) if instance_variable_defined?(:@_prepended_block)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
126
153
|
# Evaluate given block in context of base class,
|
127
154
|
# so that you can write class macros here.
|
128
155
|
# When you define more than one +included+ block, it raises an exception.
|
@@ -140,6 +167,23 @@ module ActiveSupport
|
|
140
167
|
end
|
141
168
|
end
|
142
169
|
|
170
|
+
# Evaluate given block in context of base class,
|
171
|
+
# so that you can write class macros here.
|
172
|
+
# When you define more than one +prepended+ block, it raises an exception.
|
173
|
+
def prepended(base = nil, &block)
|
174
|
+
if base.nil?
|
175
|
+
if instance_variable_defined?(:@_prepended_block)
|
176
|
+
if @_prepended_block.source_location != block.source_location
|
177
|
+
raise MultiplePrependBlocks
|
178
|
+
end
|
179
|
+
else
|
180
|
+
@_prepended_block = block
|
181
|
+
end
|
182
|
+
else
|
183
|
+
super
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
143
187
|
# Define class methods from given block.
|
144
188
|
# You can define private class methods as well.
|
145
189
|
#
|
@@ -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 <tt>
|
8
|
+
# configuration options as an <tt>OrderedOptions</tt>.
|
9
9
|
module Configurable
|
10
10
|
extend ActiveSupport::Concern
|
11
11
|
|
@@ -124,9 +124,9 @@ module ActiveSupport
|
|
124
124
|
private :config_accessor
|
125
125
|
end
|
126
126
|
|
127
|
-
# Reads and writes attributes from a configuration <tt>
|
127
|
+
# Reads and writes attributes from a configuration <tt>OrderedOptions</tt>.
|
128
128
|
#
|
129
|
-
# require
|
129
|
+
# require "active_support/configurable"
|
130
130
|
#
|
131
131
|
# class User
|
132
132
|
# include ActiveSupport::Configurable
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# Reads a YAML configuration file, evaluating any ERB, then
|
5
|
+
# parsing the resulting YAML.
|
6
|
+
#
|
7
|
+
# Warns in case of YAML confusing characters, like invisible
|
8
|
+
# non-breaking spaces.
|
9
|
+
class ConfigurationFile # :nodoc:
|
10
|
+
class FormatError < StandardError; end
|
11
|
+
|
12
|
+
def initialize(content_path)
|
13
|
+
@content_path = content_path.to_s
|
14
|
+
@content = read content_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.parse(content_path, **options)
|
18
|
+
new(content_path).parse(**options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(context: nil, **options)
|
22
|
+
YAML.load(render(context), **options) || {}
|
23
|
+
rescue Psych::SyntaxError => error
|
24
|
+
raise "YAML syntax error occurred while parsing #{@content_path}. " \
|
25
|
+
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
|
26
|
+
"Error: #{error.message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def read(content_path)
|
31
|
+
require "yaml"
|
32
|
+
require "erb"
|
33
|
+
|
34
|
+
File.read(content_path).tap do |content|
|
35
|
+
if content.include?("\u00A0")
|
36
|
+
warn "File contains invisible non-breaking spaces, you may want to remove those"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def render(context)
|
42
|
+
erb = ERB.new(@content).tap { |e| e.filename = @content_path }
|
43
|
+
context ? erb.result(context) : erb.result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|