activesupport 5.2.8.1 → 6.1.6.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 +426 -424
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +29 -3
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +34 -34
- data/lib/active_support/cache/mem_cache_store.rb +39 -24
- data/lib/active_support/cache/memory_store.rb +59 -33
- data/lib/active_support/cache/null_store.rb +8 -3
- data/lib/active_support/cache/redis_cache_store.rb +72 -45
- data/lib/active_support/cache/strategy/local_cache.rb +41 -26
- data/lib/active_support/cache.rb +148 -78
- data/lib/active_support/callbacks.rb +81 -64
- data/lib/active_support/concern.rb +70 -3
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/configurable.rb +10 -14
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/array/conversions.rb +5 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array.rb +1 -1
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +32 -47
- data/lib/active_support/core_ext/class/subclasses.rb +17 -38
- data/lib/active_support/core_ext/date/calculations.rb +6 -5
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -0
- data/lib/active_support/core_ext/enumerable.rb +171 -75
- data/lib/active_support/core_ext/hash/conversions.rb +3 -3
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +2 -2
- data/lib/active_support/core_ext/hash/keys.rb +1 -30
- data/lib/active_support/core_ext/hash/slice.rb +6 -27
- data/lib/active_support/core_ext/hash.rb +1 -2
- data/lib/active_support/core_ext/integer/multiple.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- 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 +30 -39
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +76 -33
- data/lib/active_support/core_ext/module/introspection.rb +16 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/name_error.rb +29 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/blank.rb +1 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +7 -114
- data/lib/active_support/core_ext/object/json.rb +14 -2
- data/lib/active_support/core_ext/object/try.rb +17 -7
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/compare_range.rb +34 -13
- data/lib/active_support/core_ext/range/conversions.rb +31 -29
- data/lib/active_support/core_ext/range/each.rb +0 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
- data/lib/active_support/core_ext/regexp.rb +8 -5
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +5 -16
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/filters.rb +42 -1
- data/lib/active_support/core_ext/string/inflections.rb +45 -6
- data/lib/active_support/core_ext/string/inquiry.rb +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +6 -5
- data/lib/active_support/core_ext/string/output_safety.rb +70 -13
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- 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 +53 -3
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +6 -1
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +16 -2
- data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
- data/lib/active_support/dependencies.rb +109 -34
- data/lib/active_support/deprecation/behaviors.rb +16 -3
- 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 +18 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/descendants_tracker.rb +59 -9
- data/lib/active_support/digest.rb +2 -0
- data/lib/active_support/duration/iso8601_parser.rb +2 -4
- data/lib/active_support/duration/iso8601_serializer.rb +18 -14
- data/lib/active_support/duration.rb +82 -33
- data/lib/active_support/encrypted_configuration.rb +0 -4
- data/lib/active_support/encrypted_file.rb +22 -4
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +82 -117
- data/lib/active_support/execution_wrapper.rb +2 -1
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +70 -42
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +15 -8
- data/lib/active_support/inflector/inflections.rb +2 -7
- data/lib/active_support/inflector/methods.rb +49 -58
- data/lib/active_support/inflector/transliterate.rb +47 -18
- data/lib/active_support/json/decoding.rb +25 -26
- data/lib/active_support/json/encoding.rb +11 -3
- data/lib/active_support/key_generator.rb +1 -33
- data/lib/active_support/lazy_load_hooks.rb +5 -2
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber.rb +39 -9
- data/lib/active_support/logger.rb +2 -17
- data/lib/active_support/logger_silence.rb +11 -19
- data/lib/active_support/logger_thread_safe_level.rb +50 -6
- data/lib/active_support/message_encryptor.rb +8 -13
- data/lib/active_support/message_verifier.rb +10 -10
- data/lib/active_support/messages/metadata.rb +11 -2
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +10 -9
- data/lib/active_support/multibyte/chars.rb +10 -68
- data/lib/active_support/multibyte/unicode.rb +15 -327
- data/lib/active_support/notifications/fanout.rb +116 -16
- data/lib/active_support/notifications/instrumenter.rb +71 -9
- data/lib/active_support/notifications.rb +72 -8
- data/lib/active_support/number_helper/number_converter.rb +5 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -7
- data/lib/active_support/number_helper/rounding_helper.rb +12 -28
- data/lib/active_support/number_helper.rb +38 -12
- data/lib/active_support/option_merger.rb +22 -3
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +13 -3
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +2 -1
- data/lib/active_support/rails.rb +1 -10
- data/lib/active_support/railtie.rb +23 -1
- data/lib/active_support/reloader.rb +4 -5
- data/lib/active_support/rescuable.rb +4 -4
- 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 -3
- data/lib/active_support/subscriber.rb +72 -28
- data/lib/active_support/tagged_logging.rb +42 -8
- data/lib/active_support/test_case.rb +91 -0
- data/lib/active_support/testing/assertions.rb +30 -9
- data/lib/active_support/testing/deprecation.rb +0 -1
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +28 -1
- 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 +51 -0
- data/lib/active_support/testing/stream.rb +1 -2
- data/lib/active_support/testing/time_helpers.rb +47 -12
- data/lib/active_support/time_with_zone.rb +81 -47
- data/lib/active_support/values/time_zone.rb +34 -17
- data/lib/active_support/xml_mini/jdom.rb +2 -3
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
- data/lib/active_support/xml_mini/rexml.rb +10 -3
- data/lib/active_support/xml_mini.rb +2 -10
- data/lib/active_support.rb +14 -1
- metadata +54 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
- data/lib/active_support/core_ext/hash/compact.rb +0 -29
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/core_ext/module/reachable.rb +0 -11
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
- data/lib/active_support/core_ext/range/include_range.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -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
|
@@ -23,6 +20,9 @@ module ActiveSupport
|
|
23
20
|
# +ClassMethods.set_callback+), and run the installed callbacks at the
|
24
21
|
# appropriate times (via +run_callbacks+).
|
25
22
|
#
|
23
|
+
# By default callbacks are halted by throwing +:abort+.
|
24
|
+
# See +ClassMethods.define_callbacks+ for details.
|
25
|
+
#
|
26
26
|
# Three kinds of callbacks are supported: before callbacks, run before a
|
27
27
|
# certain event; after callbacks, run after the event; and around callbacks,
|
28
28
|
# blocks that surround the event, triggering it when they yield. Callback code
|
@@ -100,32 +100,6 @@ module ActiveSupport
|
|
100
100
|
env = Filters::Environment.new(self, false, nil)
|
101
101
|
next_sequence = callbacks.compile
|
102
102
|
|
103
|
-
invoke_sequence = Proc.new do
|
104
|
-
skipped = nil
|
105
|
-
while true
|
106
|
-
current = next_sequence
|
107
|
-
current.invoke_before(env)
|
108
|
-
if current.final?
|
109
|
-
env.value = !env.halted && (!block_given? || yield)
|
110
|
-
elsif current.skip?(env)
|
111
|
-
(skipped ||= []) << current
|
112
|
-
next_sequence = next_sequence.nested
|
113
|
-
next
|
114
|
-
else
|
115
|
-
next_sequence = next_sequence.nested
|
116
|
-
begin
|
117
|
-
target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
|
118
|
-
target.send(method, *arguments, &block)
|
119
|
-
ensure
|
120
|
-
next_sequence = current
|
121
|
-
end
|
122
|
-
end
|
123
|
-
current.invoke_after(env)
|
124
|
-
skipped.pop.invoke_after(env) while skipped && skipped.first
|
125
|
-
break env.value
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
103
|
# Common case: no 'around' callbacks defined
|
130
104
|
if next_sequence.final?
|
131
105
|
next_sequence.invoke_before(env)
|
@@ -133,17 +107,43 @@ module ActiveSupport
|
|
133
107
|
next_sequence.invoke_after(env)
|
134
108
|
env.value
|
135
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
|
+
|
136
137
|
invoke_sequence.call
|
137
138
|
end
|
138
139
|
end
|
139
140
|
end
|
140
141
|
|
141
142
|
private
|
142
|
-
|
143
143
|
# A hook invoked every time a before callback is halted.
|
144
144
|
# This can be overridden in ActiveSupport::Callbacks implementors in order
|
145
145
|
# to provide better debugging/logging.
|
146
|
-
def halted_callback_hook(filter)
|
146
|
+
def halted_callback_hook(filter, name)
|
147
147
|
end
|
148
148
|
|
149
149
|
module Conditionals # :nodoc:
|
@@ -159,17 +159,17 @@ module ActiveSupport
|
|
159
159
|
Environment = Struct.new(:target, :halted, :value)
|
160
160
|
|
161
161
|
class Before
|
162
|
-
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)
|
163
163
|
halted_lambda = chain_config[:terminator]
|
164
164
|
|
165
165
|
if user_conditions.any?
|
166
|
-
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)
|
167
167
|
else
|
168
|
-
halting(callback_sequence, user_callback, halted_lambda, filter)
|
168
|
+
halting(callback_sequence, user_callback, halted_lambda, filter, name)
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
-
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)
|
173
173
|
callback_sequence.before do |env|
|
174
174
|
target = env.target
|
175
175
|
value = env.value
|
@@ -179,7 +179,7 @@ module ActiveSupport
|
|
179
179
|
result_lambda = -> { user_callback.call target, value }
|
180
180
|
env.halted = halted_lambda.call(target, result_lambda)
|
181
181
|
if env.halted
|
182
|
-
target.send :halted_callback_hook, filter
|
182
|
+
target.send :halted_callback_hook, filter, name
|
183
183
|
end
|
184
184
|
end
|
185
185
|
|
@@ -188,7 +188,7 @@ module ActiveSupport
|
|
188
188
|
end
|
189
189
|
private_class_method :halting_and_conditional
|
190
190
|
|
191
|
-
def self.halting(callback_sequence, user_callback, halted_lambda, filter)
|
191
|
+
def self.halting(callback_sequence, user_callback, halted_lambda, filter, name)
|
192
192
|
callback_sequence.before do |env|
|
193
193
|
target = env.target
|
194
194
|
value = env.value
|
@@ -197,9 +197,8 @@ module ActiveSupport
|
|
197
197
|
unless halted
|
198
198
|
result_lambda = -> { user_callback.call target, value }
|
199
199
|
env.halted = halted_lambda.call(target, result_lambda)
|
200
|
-
|
201
200
|
if env.halted
|
202
|
-
target.send :halted_callback_hook, filter
|
201
|
+
target.send :halted_callback_hook, filter, name
|
203
202
|
end
|
204
203
|
end
|
205
204
|
|
@@ -298,8 +297,8 @@ module ActiveSupport
|
|
298
297
|
@kind = kind
|
299
298
|
@filter = filter
|
300
299
|
@key = compute_identifier filter
|
301
|
-
@if = check_conditionals(
|
302
|
-
@unless = check_conditionals(
|
300
|
+
@if = check_conditionals(options[:if])
|
301
|
+
@unless = check_conditionals(options[:unless])
|
303
302
|
end
|
304
303
|
|
305
304
|
def filter; @key; end
|
@@ -337,7 +336,7 @@ module ActiveSupport
|
|
337
336
|
|
338
337
|
case kind
|
339
338
|
when :before
|
340
|
-
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)
|
341
340
|
when :after
|
342
341
|
Filters::After.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config)
|
343
342
|
when :around
|
@@ -350,7 +349,13 @@ module ActiveSupport
|
|
350
349
|
end
|
351
350
|
|
352
351
|
private
|
352
|
+
EMPTY_ARRAY = [].freeze
|
353
|
+
private_constant :EMPTY_ARRAY
|
354
|
+
|
353
355
|
def check_conditionals(conditionals)
|
356
|
+
return EMPTY_ARRAY if conditionals.blank?
|
357
|
+
|
358
|
+
conditionals = Array(conditionals)
|
354
359
|
if conditionals.any? { |c| c.is_a?(String) }
|
355
360
|
raise ArgumentError, <<-MSG.squish
|
356
361
|
Passing string to be evaluated in :if and :unless conditional
|
@@ -359,7 +364,7 @@ module ActiveSupport
|
|
359
364
|
MSG
|
360
365
|
end
|
361
366
|
|
362
|
-
conditionals
|
367
|
+
conditionals.freeze
|
363
368
|
end
|
364
369
|
|
365
370
|
def compute_identifier(filter)
|
@@ -401,21 +406,17 @@ module ActiveSupport
|
|
401
406
|
# The actual invocation is left up to the caller to minimize
|
402
407
|
# call stack pollution.
|
403
408
|
def expand(target, value, block)
|
404
|
-
|
409
|
+
expanded = [@override_target || target, @override_block || block, @method_name]
|
410
|
+
|
411
|
+
@arguments.each do |arg|
|
405
412
|
case arg
|
406
|
-
when :value
|
407
|
-
when :target
|
408
|
-
when :block
|
413
|
+
when :value then expanded << value
|
414
|
+
when :target then expanded << target
|
415
|
+
when :block then expanded << (block || raise(ArgumentError))
|
409
416
|
end
|
410
|
-
|
411
|
-
|
412
|
-
result.unshift @method_name
|
413
|
-
result.unshift @override_block || block
|
414
|
-
result.unshift @override_target || target
|
417
|
+
end
|
415
418
|
|
416
|
-
|
417
|
-
# target.send(method, *arguments, &block)
|
418
|
-
result
|
419
|
+
expanded
|
419
420
|
end
|
420
421
|
|
421
422
|
# Return a lambda that will make this call when given the input
|
@@ -497,9 +498,7 @@ module ActiveSupport
|
|
497
498
|
arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
|
498
499
|
end
|
499
500
|
|
500
|
-
|
501
|
-
@nested
|
502
|
-
end
|
501
|
+
attr_reader :nested
|
503
502
|
|
504
503
|
def final?
|
505
504
|
!@call_template
|
@@ -578,10 +577,9 @@ module ActiveSupport
|
|
578
577
|
end
|
579
578
|
|
580
579
|
protected
|
581
|
-
|
580
|
+
attr_reader :chain
|
582
581
|
|
583
582
|
private
|
584
|
-
|
585
583
|
def append_one(callback)
|
586
584
|
@callbacks = nil
|
587
585
|
remove_duplicates(callback)
|
@@ -659,9 +657,17 @@ module ActiveSupport
|
|
659
657
|
# * <tt>:if</tt> - A symbol or an array of symbols, each naming an instance
|
660
658
|
# method or a proc; the callback will be called only when they all return
|
661
659
|
# a true value.
|
660
|
+
#
|
661
|
+
# If a proc is given, its body is evaluated in the context of the
|
662
|
+
# current object. It can also optionally accept the current object as
|
663
|
+
# an argument.
|
662
664
|
# * <tt>:unless</tt> - A symbol or an array of symbols, each naming an
|
663
665
|
# instance method or a proc; the callback will be called only when they
|
664
666
|
# all return a false value.
|
667
|
+
#
|
668
|
+
# If a proc is given, its body is evaluated in the context of the
|
669
|
+
# current object. It can also optionally accept the current object as
|
670
|
+
# an argument.
|
665
671
|
# * <tt>:prepend</tt> - If +true+, the callback will be prepended to the
|
666
672
|
# existing chain rather than appended.
|
667
673
|
def set_callback(name, *filter_list, &block)
|
@@ -809,7 +815,9 @@ module ActiveSupport
|
|
809
815
|
names.each do |name|
|
810
816
|
name = name.to_sym
|
811
817
|
|
812
|
-
|
818
|
+
([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target|
|
819
|
+
target.set_callbacks name, CallbackChain.new(name, options)
|
820
|
+
end
|
813
821
|
|
814
822
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
815
823
|
def _run_#{name}_callbacks(&block)
|
@@ -832,13 +840,22 @@ module ActiveSupport
|
|
832
840
|
end
|
833
841
|
|
834
842
|
protected
|
835
|
-
|
836
843
|
def get_callbacks(name) # :nodoc:
|
837
844
|
__callbacks[name.to_sym]
|
838
845
|
end
|
839
846
|
|
840
|
-
|
841
|
-
|
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
|
842
859
|
end
|
843
860
|
end
|
844
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 <tt>include</tt>, concerns also support <tt>prepend</tt> with a corresponding
|
106
|
+
# <tt>prepended do</tt> callback. <tt>module ClassMethods</tt> or <tt>class_methods do</tt> are
|
107
|
+
# prepended as well.
|
108
|
+
#
|
109
|
+
# <tt>prepend</tt> is also used for any dependencies.
|
102
110
|
module Concern
|
103
111
|
class MultipleIncludedBlocks < StandardError #:nodoc:
|
104
112
|
def initialize
|
@@ -106,11 +114,17 @@ 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
|
112
126
|
|
113
|
-
def append_features(base)
|
127
|
+
def append_features(base) #:nodoc:
|
114
128
|
if base.instance_variable_defined?(:@_dependencies)
|
115
129
|
base.instance_variable_get(:@_dependencies) << self
|
116
130
|
false
|
@@ -123,6 +137,22 @@ 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
|
+
|
153
|
+
# Evaluate given block in context of base class,
|
154
|
+
# so that you can write class macros here.
|
155
|
+
# When you define more than one +included+ block, it raises an exception.
|
126
156
|
def included(base = nil, &block)
|
127
157
|
if base.nil?
|
128
158
|
if instance_variable_defined?(:@_included_block)
|
@@ -137,6 +167,43 @@ module ActiveSupport
|
|
137
167
|
end
|
138
168
|
end
|
139
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
|
+
|
187
|
+
# Define class methods from given block.
|
188
|
+
# You can define private class methods as well.
|
189
|
+
#
|
190
|
+
# module Example
|
191
|
+
# extend ActiveSupport::Concern
|
192
|
+
#
|
193
|
+
# class_methods do
|
194
|
+
# def foo; puts 'foo'; end
|
195
|
+
#
|
196
|
+
# private
|
197
|
+
# def bar; puts 'bar'; end
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# class Buzz
|
202
|
+
# include Example
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# Buzz.foo # => "foo"
|
206
|
+
# Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)
|
140
207
|
def class_methods(&class_methods_module_definition)
|
141
208
|
mod = const_defined?(:ClassMethods, false) ?
|
142
209
|
const_get(:ClassMethods) :
|
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
require "active_support/concern"
|
4
4
|
require "active_support/ordered_options"
|
5
|
-
require "active_support/core_ext/array/extract_options"
|
6
|
-
require "active_support/core_ext/regexp"
|
7
5
|
|
8
6
|
module ActiveSupport
|
9
7
|
# Configurable provides a <tt>config</tt> method to store and retrieve
|
10
|
-
# configuration options as an <tt>
|
8
|
+
# configuration options as an <tt>OrderedOptions</tt>.
|
11
9
|
module Configurable
|
12
10
|
extend ActiveSupport::Concern
|
13
11
|
|
@@ -69,8 +67,8 @@ module ActiveSupport
|
|
69
67
|
# end
|
70
68
|
# # => NameError: invalid config attribute name
|
71
69
|
#
|
72
|
-
# To
|
73
|
-
# To
|
70
|
+
# To omit the instance writer method, pass <tt>instance_writer: false</tt>.
|
71
|
+
# To omit the instance reader method, pass <tt>instance_reader: false</tt>.
|
74
72
|
#
|
75
73
|
# class User
|
76
74
|
# include ActiveSupport::Configurable
|
@@ -83,7 +81,7 @@ module ActiveSupport
|
|
83
81
|
# User.new.allowed_access = true # => NoMethodError
|
84
82
|
# User.new.allowed_access # => NoMethodError
|
85
83
|
#
|
86
|
-
# Or pass <tt>instance_accessor: false</tt>, to
|
84
|
+
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
|
87
85
|
#
|
88
86
|
# class User
|
89
87
|
# include ActiveSupport::Configurable
|
@@ -106,9 +104,7 @@ module ActiveSupport
|
|
106
104
|
# end
|
107
105
|
#
|
108
106
|
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
109
|
-
def config_accessor(*names)
|
110
|
-
options = names.extract_options!
|
111
|
-
|
107
|
+
def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
|
112
108
|
names.each do |name|
|
113
109
|
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
|
114
110
|
|
@@ -118,9 +114,9 @@ module ActiveSupport
|
|
118
114
|
singleton_class.class_eval reader, __FILE__, reader_line
|
119
115
|
singleton_class.class_eval writer, __FILE__, writer_line
|
120
116
|
|
121
|
-
|
122
|
-
class_eval reader, __FILE__, reader_line
|
123
|
-
class_eval writer, __FILE__, writer_line
|
117
|
+
if instance_accessor
|
118
|
+
class_eval reader, __FILE__, reader_line if instance_reader
|
119
|
+
class_eval writer, __FILE__, writer_line if instance_writer
|
124
120
|
end
|
125
121
|
send("#{name}=", yield) if block_given?
|
126
122
|
end
|
@@ -128,9 +124,9 @@ module ActiveSupport
|
|
128
124
|
private :config_accessor
|
129
125
|
end
|
130
126
|
|
131
|
-
# Reads and writes attributes from a configuration <tt>
|
127
|
+
# Reads and writes attributes from a configuration <tt>OrderedOptions</tt>.
|
132
128
|
#
|
133
|
-
# require
|
129
|
+
# require "active_support/configurable"
|
134
130
|
#
|
135
131
|
# class User
|
136
132
|
# include ActiveSupport::Configurable
|
@@ -0,0 +1,51 @@
|
|
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
|
+
source = render(context)
|
23
|
+
if YAML.respond_to?(:unsafe_load)
|
24
|
+
YAML.unsafe_load(source, **options) || {}
|
25
|
+
else
|
26
|
+
YAML.load(source, **options) || {}
|
27
|
+
end
|
28
|
+
rescue Psych::SyntaxError => error
|
29
|
+
raise "YAML syntax error occurred while parsing #{@content_path}. " \
|
30
|
+
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
|
31
|
+
"Error: #{error.message}"
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def read(content_path)
|
36
|
+
require "yaml"
|
37
|
+
require "erb"
|
38
|
+
|
39
|
+
File.read(content_path).tap do |content|
|
40
|
+
if content.include?("\u00A0")
|
41
|
+
warn "File contains invisible non-breaking spaces, you may want to remove those"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def render(context)
|
47
|
+
erb = ERB.new(@content).tap { |e| e.filename = @content_path }
|
48
|
+
context ? erb.result(context) : erb.result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -29,16 +29,28 @@ class Array
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
# Returns a
|
32
|
+
# Returns a new array that includes the passed elements.
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
|
34
|
+
# [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
|
35
|
+
# [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
|
36
|
+
def including(*elements)
|
37
|
+
self + elements.flatten(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a copy of the Array excluding the specified elements.
|
41
|
+
#
|
42
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
|
43
|
+
# [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
|
37
44
|
#
|
38
|
-
# Note: This is an optimization of <tt>Enumerable#
|
45
|
+
# Note: This is an optimization of <tt>Enumerable#excluding</tt> that uses <tt>Array#-</tt>
|
39
46
|
# instead of <tt>Array#reject</tt> for performance reasons.
|
47
|
+
def excluding(*elements)
|
48
|
+
self - elements.flatten(1)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Alias for #excluding.
|
40
52
|
def without(*elements)
|
41
|
-
|
53
|
+
excluding(*elements)
|
42
54
|
end
|
43
55
|
|
44
56
|
# Equal to <tt>self[1]</tt>.
|
@@ -74,13 +74,13 @@ class Array
|
|
74
74
|
|
75
75
|
case length
|
76
76
|
when 0
|
77
|
-
""
|
77
|
+
+""
|
78
78
|
when 1
|
79
|
-
"#{self[0]}"
|
79
|
+
+"#{self[0]}"
|
80
80
|
when 2
|
81
|
-
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
81
|
+
+"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
82
82
|
else
|
83
|
-
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
83
|
+
+"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -181,7 +181,7 @@ class Array
|
|
181
181
|
# </messages>
|
182
182
|
#
|
183
183
|
def to_xml(options = {})
|
184
|
-
require "active_support/builder" unless defined?(Builder)
|
184
|
+
require "active_support/builder" unless defined?(Builder::XmlMarkup)
|
185
185
|
|
186
186
|
options = options.dup
|
187
187
|
options[:indent] ||= 2
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Array
|
4
|
+
# Removes and returns the elements for which the block returns a true value.
|
5
|
+
# If no block is given, an Enumerator is returned instead.
|
6
|
+
#
|
7
|
+
# numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
8
|
+
# odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
|
9
|
+
# numbers # => [0, 2, 4, 6, 8]
|
10
|
+
def extract!
|
11
|
+
return to_enum(:extract!) { size } unless block_given?
|
12
|
+
|
13
|
+
extracted_elements = []
|
14
|
+
|
15
|
+
reject! do |element|
|
16
|
+
extracted_elements << element if yield(element)
|
17
|
+
end
|
18
|
+
|
19
|
+
extracted_elements
|
20
|
+
end
|
21
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "active_support/core_ext/array/wrap"
|
4
4
|
require "active_support/core_ext/array/access"
|
5
5
|
require "active_support/core_ext/array/conversions"
|
6
|
+
require "active_support/core_ext/array/extract"
|
6
7
|
require "active_support/core_ext/array/extract_options"
|
7
8
|
require "active_support/core_ext/array/grouping"
|
8
|
-
require "active_support/core_ext/array/prepend_and_append"
|
9
9
|
require "active_support/core_ext/array/inquiry"
|