activesupport 5.2.4.4 → 6.1.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 +353 -435
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/active_support.rb +14 -1
- 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.rb +142 -78
- data/lib/active_support/cache/file_store.rb +33 -33
- data/lib/active_support/cache/mem_cache_store.rb +32 -20
- 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 +70 -43
- data/lib/active_support/cache/strategy/local_cache.rb +41 -26
- data/lib/active_support/callbacks.rb +81 -64
- data/lib/active_support/concern.rb +70 -3
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- 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 +46 -0
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/core_ext/array.rb +1 -1
- 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/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/enumerable.rb +171 -75
- data/lib/active_support/core_ext/hash.rb +1 -2
- 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/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.rb +0 -1
- 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/name_error.rb +29 -2
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
- 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.rb +3 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/time/calculations.rb +50 -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/current_attributes.rb +15 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/dependencies.rb +109 -34
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/deprecation.rb +6 -1
- 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/descendants_tracker.rb +59 -9
- data/lib/active_support/duration.rb +90 -38
- data/lib/active_support/duration/iso8601_parser.rb +2 -4
- data/lib/active_support/duration/iso8601_serializer.rb +18 -14
- 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 +1 -0
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +64 -41
- 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.rb +72 -8
- data/lib/active_support/notifications/fanout.rb +116 -16
- data/lib/active_support/notifications/instrumenter.rb +71 -9
- data/lib/active_support/number_helper.rb +38 -12
- 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 +8 -7
- data/lib/active_support/number_helper/rounding_helper.rb +12 -28
- 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 +1 -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.rb +51 -0
- 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/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 +32 -17
- data/lib/active_support/xml_mini.rb +2 -10
- 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
- metadata +58 -32
- 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
@@ -12,6 +12,11 @@ module ActiveSupport
|
|
12
12
|
class NullStore < Store
|
13
13
|
prepend Strategy::LocalCache
|
14
14
|
|
15
|
+
# Advertise cache versioning support.
|
16
|
+
def self.supports_cache_versioning?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
15
20
|
def clear(options = nil)
|
16
21
|
end
|
17
22
|
|
@@ -28,14 +33,14 @@ module ActiveSupport
|
|
28
33
|
end
|
29
34
|
|
30
35
|
private
|
31
|
-
def read_entry(key, options)
|
36
|
+
def read_entry(key, **options)
|
32
37
|
end
|
33
38
|
|
34
|
-
def write_entry(key, entry, options)
|
39
|
+
def write_entry(key, entry, **options)
|
35
40
|
true
|
36
41
|
end
|
37
42
|
|
38
|
-
def delete_entry(key, options)
|
43
|
+
def delete_entry(key, **options)
|
39
44
|
false
|
40
45
|
end
|
41
46
|
end
|
@@ -17,7 +17,6 @@ end
|
|
17
17
|
|
18
18
|
require "digest/sha2"
|
19
19
|
require "active_support/core_ext/marshal"
|
20
|
-
require "active_support/core_ext/hash/transform_values"
|
21
20
|
|
22
21
|
module ActiveSupport
|
23
22
|
module Cache
|
@@ -67,27 +66,32 @@ module ActiveSupport
|
|
67
66
|
SCAN_BATCH_SIZE = 1000
|
68
67
|
private_constant :SCAN_BATCH_SIZE
|
69
68
|
|
69
|
+
# Advertise cache versioning support.
|
70
|
+
def self.supports_cache_versioning?
|
71
|
+
true
|
72
|
+
end
|
73
|
+
|
70
74
|
# Support raw values in the local cache strategy.
|
71
75
|
module LocalCacheWithRaw # :nodoc:
|
72
76
|
private
|
73
|
-
def write_entry(key, entry, options)
|
77
|
+
def write_entry(key, entry, **options)
|
74
78
|
if options[:raw] && local_cache
|
75
79
|
raw_entry = Entry.new(serialize_entry(entry, raw: true))
|
76
80
|
raw_entry.expires_at = entry.expires_at
|
77
|
-
super(key, raw_entry, options)
|
81
|
+
super(key, raw_entry, **options)
|
78
82
|
else
|
79
83
|
super
|
80
84
|
end
|
81
85
|
end
|
82
86
|
|
83
|
-
def write_multi_entries(entries, options)
|
87
|
+
def write_multi_entries(entries, **options)
|
84
88
|
if options[:raw] && local_cache
|
85
89
|
raw_entries = entries.map do |key, entry|
|
86
90
|
raw_entry = Entry.new(serialize_entry(entry, raw: true))
|
87
91
|
raw_entry.expires_at = entry.expires_at
|
88
92
|
end.to_h
|
89
93
|
|
90
|
-
super(raw_entries, options)
|
94
|
+
super(raw_entries, **options)
|
91
95
|
else
|
92
96
|
super
|
93
97
|
end
|
@@ -140,15 +144,17 @@ module ActiveSupport
|
|
140
144
|
|
141
145
|
# Creates a new Redis cache store.
|
142
146
|
#
|
143
|
-
# Handles
|
144
|
-
#
|
147
|
+
# Handles four options: :redis block, :redis instance, single :url
|
148
|
+
# string, and multiple :url strings.
|
145
149
|
#
|
146
|
-
#
|
147
|
-
# :
|
148
|
-
# :
|
150
|
+
# Option Class Result
|
151
|
+
# :redis Proc -> options[:redis].call
|
152
|
+
# :redis Object -> options[:redis]
|
153
|
+
# :url String -> Redis.new(url: …)
|
154
|
+
# :url Array -> Redis::Distributed.new([{ url: … }, { url: … }, …])
|
149
155
|
#
|
150
156
|
# No namespace is set by default. Provide one if the Redis cache
|
151
|
-
# server is shared with other apps: <tt>namespace: 'myapp-cache'
|
157
|
+
# server is shared with other apps: <tt>namespace: 'myapp-cache'</tt>.
|
152
158
|
#
|
153
159
|
# Compression is enabled by default with a 1kB threshold, so cached
|
154
160
|
# values larger than 1kB are automatically compressed. Disable by
|
@@ -163,7 +169,7 @@ module ActiveSupport
|
|
163
169
|
# Race condition TTL is not set by default. This can be used to avoid
|
164
170
|
# "thundering herd" cache writes when hot cache entries are expired.
|
165
171
|
# See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
|
166
|
-
def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
|
172
|
+
def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, coder: DEFAULT_CODER, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
|
167
173
|
@redis_options = redis_options
|
168
174
|
|
169
175
|
@max_key_bytesize = MAX_KEY_BYTESIZE
|
@@ -171,7 +177,8 @@ module ActiveSupport
|
|
171
177
|
|
172
178
|
super namespace: namespace,
|
173
179
|
compress: compress, compress_threshold: compress_threshold,
|
174
|
-
expires_in: expires_in, race_condition_ttl: race_condition_ttl
|
180
|
+
expires_in: expires_in, race_condition_ttl: race_condition_ttl,
|
181
|
+
coder: coder
|
175
182
|
end
|
176
183
|
|
177
184
|
def redis
|
@@ -189,7 +196,7 @@ module ActiveSupport
|
|
189
196
|
|
190
197
|
def inspect
|
191
198
|
instance = @redis || @redis_options
|
192
|
-
"
|
199
|
+
"#<#{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
|
193
200
|
end
|
194
201
|
|
195
202
|
# Cache Store API implementation.
|
@@ -232,10 +239,14 @@ module ActiveSupport
|
|
232
239
|
pattern = namespace_key(matcher, options)
|
233
240
|
cursor = "0"
|
234
241
|
# Fetch keys in batches using SCAN to avoid blocking the Redis server.
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
242
|
+
nodes = c.respond_to?(:nodes) ? c.nodes : [c]
|
243
|
+
|
244
|
+
nodes.each do |node|
|
245
|
+
begin
|
246
|
+
cursor, keys = node.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
|
247
|
+
node.del(*keys) unless keys.empty?
|
248
|
+
end until cursor == "0"
|
249
|
+
end
|
239
250
|
end
|
240
251
|
end
|
241
252
|
end
|
@@ -251,7 +262,14 @@ module ActiveSupport
|
|
251
262
|
def increment(name, amount = 1, options = nil)
|
252
263
|
instrument :increment, name, amount: amount do
|
253
264
|
failsafe :increment do
|
254
|
-
|
265
|
+
options = merged_options(options)
|
266
|
+
key = normalize_key(name, options)
|
267
|
+
|
268
|
+
redis.with do |c|
|
269
|
+
c.incrby(key, amount).tap do
|
270
|
+
write_key_expiry(c, key, options)
|
271
|
+
end
|
272
|
+
end
|
255
273
|
end
|
256
274
|
end
|
257
275
|
end
|
@@ -267,7 +285,14 @@ module ActiveSupport
|
|
267
285
|
def decrement(name, amount = 1, options = nil)
|
268
286
|
instrument :decrement, name, amount: amount do
|
269
287
|
failsafe :decrement do
|
270
|
-
|
288
|
+
options = merged_options(options)
|
289
|
+
key = normalize_key(name, options)
|
290
|
+
|
291
|
+
redis.with do |c|
|
292
|
+
c.decrby(key, amount).tap do
|
293
|
+
write_key_expiry(c, key, options)
|
294
|
+
end
|
295
|
+
end
|
271
296
|
end
|
272
297
|
end
|
273
298
|
end
|
@@ -318,16 +343,16 @@ module ActiveSupport
|
|
318
343
|
|
319
344
|
# Store provider interface:
|
320
345
|
# Read an entry from the cache.
|
321
|
-
def read_entry(key, options
|
346
|
+
def read_entry(key, **options)
|
322
347
|
failsafe :read_entry do
|
323
348
|
raw = options&.fetch(:raw, false)
|
324
349
|
deserialize_entry(redis.with { |c| c.get(key) }, raw: raw)
|
325
350
|
end
|
326
351
|
end
|
327
352
|
|
328
|
-
def read_multi_entries(names,
|
353
|
+
def read_multi_entries(names, **options)
|
329
354
|
if mget_capable?
|
330
|
-
read_multi_mget(*names)
|
355
|
+
read_multi_mget(*names, **options)
|
331
356
|
else
|
332
357
|
super
|
333
358
|
end
|
@@ -336,6 +361,7 @@ module ActiveSupport
|
|
336
361
|
def read_multi_mget(*names)
|
337
362
|
options = names.extract_options!
|
338
363
|
options = merged_options(options)
|
364
|
+
return {} if names == []
|
339
365
|
raw = options&.fetch(:raw, false)
|
340
366
|
|
341
367
|
keys = names.map { |name| normalize_key(name, options) }
|
@@ -373,13 +399,19 @@ module ActiveSupport
|
|
373
399
|
modifiers[:nx] = unless_exist
|
374
400
|
modifiers[:px] = (1000 * expires_in.to_f).ceil if expires_in
|
375
401
|
|
376
|
-
redis.with { |c| c.set key, serialized_entry, modifiers }
|
402
|
+
redis.with { |c| c.set key, serialized_entry, **modifiers }
|
377
403
|
else
|
378
404
|
redis.with { |c| c.set key, serialized_entry }
|
379
405
|
end
|
380
406
|
end
|
381
407
|
end
|
382
408
|
|
409
|
+
def write_key_expiry(client, key, options)
|
410
|
+
if options[:expires_in] && client.ttl(key).negative?
|
411
|
+
client.expire key, options[:expires_in].to_i
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
383
415
|
# Delete an entry from the cache.
|
384
416
|
def delete_entry(key, options)
|
385
417
|
failsafe :delete_entry, returning: false do
|
@@ -387,6 +419,11 @@ module ActiveSupport
|
|
387
419
|
end
|
388
420
|
end
|
389
421
|
|
422
|
+
# Deletes multiple entries in the cache. Returns the number of entries deleted.
|
423
|
+
def delete_multi_entries(entries, **_options)
|
424
|
+
redis.with { |c| c.del(entries) }
|
425
|
+
end
|
426
|
+
|
390
427
|
# Nonstandard store provider API to write multiple values at once.
|
391
428
|
def write_multi_entries(entries, expires_in: nil, **options)
|
392
429
|
if entries.any?
|
@@ -402,11 +439,11 @@ module ActiveSupport
|
|
402
439
|
|
403
440
|
# Truncate keys that exceed 1kB.
|
404
441
|
def normalize_key(key, options)
|
405
|
-
truncate_key super
|
442
|
+
truncate_key super&.b
|
406
443
|
end
|
407
444
|
|
408
445
|
def truncate_key(key)
|
409
|
-
if key.bytesize > max_key_bytesize
|
446
|
+
if key && key.bytesize > max_key_bytesize
|
410
447
|
suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
|
411
448
|
truncate_at = max_key_bytesize - suffix.bytesize
|
412
449
|
"#{key.byteslice(0, truncate_at)}#{suffix}"
|
@@ -415,21 +452,11 @@ module ActiveSupport
|
|
415
452
|
end
|
416
453
|
end
|
417
454
|
|
418
|
-
def deserialize_entry(
|
419
|
-
if
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
if raw != written_raw
|
424
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
425
|
-
Using a different value for the raw option when reading and writing
|
426
|
-
to a cache key is deprecated for :redis_cache_store and Rails 6.0
|
427
|
-
will stop automatically detecting the format when reading to avoid
|
428
|
-
marshal loading untrusted raw strings.
|
429
|
-
MSG
|
430
|
-
end
|
431
|
-
|
432
|
-
entry.is_a?(Entry) ? entry : Entry.new(entry)
|
455
|
+
def deserialize_entry(payload, raw:)
|
456
|
+
if payload && raw
|
457
|
+
Entry.new(payload, compress: false)
|
458
|
+
else
|
459
|
+
super(payload)
|
433
460
|
end
|
434
461
|
end
|
435
462
|
|
@@ -437,7 +464,7 @@ module ActiveSupport
|
|
437
464
|
if raw
|
438
465
|
entry.value.to_s
|
439
466
|
else
|
440
|
-
|
467
|
+
super(entry)
|
441
468
|
end
|
442
469
|
end
|
443
470
|
|
@@ -449,7 +476,7 @@ module ActiveSupport
|
|
449
476
|
|
450
477
|
def failsafe(method, returning: nil)
|
451
478
|
yield
|
452
|
-
rescue ::Redis::
|
479
|
+
rescue ::Redis::BaseError => e
|
453
480
|
handle_exception exception: e, method: method, returning: returning
|
454
481
|
returning
|
455
482
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/object/duplicable"
|
4
3
|
require "active_support/core_ext/string/inflections"
|
5
4
|
require "active_support/per_thread_registry"
|
6
5
|
|
@@ -50,32 +49,36 @@ module ActiveSupport
|
|
50
49
|
@data.clear
|
51
50
|
end
|
52
51
|
|
53
|
-
def read_entry(key, options)
|
52
|
+
def read_entry(key, **options)
|
54
53
|
@data[key]
|
55
54
|
end
|
56
55
|
|
57
|
-
def read_multi_entries(keys, options)
|
56
|
+
def read_multi_entries(keys, **options)
|
58
57
|
values = {}
|
59
58
|
|
60
59
|
keys.each do |name|
|
61
|
-
entry = read_entry(name, options)
|
60
|
+
entry = read_entry(name, **options)
|
62
61
|
values[name] = entry.value if entry
|
63
62
|
end
|
64
63
|
|
65
64
|
values
|
66
65
|
end
|
67
66
|
|
68
|
-
def write_entry(key,
|
69
|
-
|
67
|
+
def write_entry(key, entry, **options)
|
68
|
+
entry.dup_value!
|
69
|
+
@data[key] = entry
|
70
70
|
true
|
71
71
|
end
|
72
72
|
|
73
|
-
def delete_entry(key, options)
|
73
|
+
def delete_entry(key, **options)
|
74
74
|
!!@data.delete(key)
|
75
75
|
end
|
76
76
|
|
77
77
|
def fetch_entry(key, options = nil) # :nodoc:
|
78
|
-
@data.fetch(key) { @data[key] = yield }
|
78
|
+
entry = @data.fetch(key) { @data[key] = yield }
|
79
|
+
dup_entry = entry.dup
|
80
|
+
dup_entry&.dup_value!
|
81
|
+
dup_entry
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
@@ -92,77 +95,89 @@ module ActiveSupport
|
|
92
95
|
local_cache_key)
|
93
96
|
end
|
94
97
|
|
95
|
-
def clear(options
|
98
|
+
def clear(**options) # :nodoc:
|
96
99
|
return super unless cache = local_cache
|
97
100
|
cache.clear(options)
|
98
101
|
super
|
99
102
|
end
|
100
103
|
|
101
|
-
def cleanup(options
|
104
|
+
def cleanup(**options) # :nodoc:
|
102
105
|
return super unless cache = local_cache
|
103
106
|
cache.clear
|
104
107
|
super
|
105
108
|
end
|
106
109
|
|
107
|
-
def
|
110
|
+
def delete_matched(matcher, options = nil) # :nodoc:
|
111
|
+
return super unless cache = local_cache
|
112
|
+
cache.clear
|
113
|
+
super
|
114
|
+
end
|
115
|
+
|
116
|
+
def increment(name, amount = 1, **options) # :nodoc:
|
108
117
|
return super unless local_cache
|
109
118
|
value = bypass_local_cache { super }
|
110
|
-
write_cache_value(name, value, options)
|
119
|
+
write_cache_value(name, value, **options)
|
111
120
|
value
|
112
121
|
end
|
113
122
|
|
114
|
-
def decrement(name, amount = 1, options
|
123
|
+
def decrement(name, amount = 1, **options) # :nodoc:
|
115
124
|
return super unless local_cache
|
116
125
|
value = bypass_local_cache { super }
|
117
|
-
write_cache_value(name, value, options)
|
126
|
+
write_cache_value(name, value, **options)
|
118
127
|
value
|
119
128
|
end
|
120
129
|
|
121
130
|
private
|
122
|
-
def read_entry(key, options)
|
131
|
+
def read_entry(key, **options)
|
123
132
|
if cache = local_cache
|
124
|
-
|
133
|
+
hit = true
|
134
|
+
value = cache.fetch_entry(key) do
|
135
|
+
hit = false
|
136
|
+
super
|
137
|
+
end
|
138
|
+
options[:event][:store] = cache.class.name if hit && options[:event]
|
139
|
+
value
|
125
140
|
else
|
126
141
|
super
|
127
142
|
end
|
128
143
|
end
|
129
144
|
|
130
|
-
def read_multi_entries(keys, options)
|
145
|
+
def read_multi_entries(keys, **options)
|
131
146
|
return super unless local_cache
|
132
147
|
|
133
|
-
local_entries = local_cache.read_multi_entries(keys, options)
|
148
|
+
local_entries = local_cache.read_multi_entries(keys, **options)
|
134
149
|
missed_keys = keys - local_entries.keys
|
135
150
|
|
136
151
|
if missed_keys.any?
|
137
|
-
local_entries.merge!(super(missed_keys, options))
|
152
|
+
local_entries.merge!(super(missed_keys, **options))
|
138
153
|
else
|
139
154
|
local_entries
|
140
155
|
end
|
141
156
|
end
|
142
157
|
|
143
|
-
def write_entry(key, entry, options)
|
158
|
+
def write_entry(key, entry, **options)
|
144
159
|
if options[:unless_exist]
|
145
|
-
local_cache.delete_entry(key, options) if local_cache
|
160
|
+
local_cache.delete_entry(key, **options) if local_cache
|
146
161
|
else
|
147
|
-
local_cache.write_entry(key, entry, options) if local_cache
|
162
|
+
local_cache.write_entry(key, entry, **options) if local_cache
|
148
163
|
end
|
149
164
|
|
150
165
|
super
|
151
166
|
end
|
152
167
|
|
153
|
-
def delete_entry(key, options)
|
154
|
-
local_cache.delete_entry(key, options) if local_cache
|
168
|
+
def delete_entry(key, **options)
|
169
|
+
local_cache.delete_entry(key, **options) if local_cache
|
155
170
|
super
|
156
171
|
end
|
157
172
|
|
158
|
-
def write_cache_value(name, value, options)
|
173
|
+
def write_cache_value(name, value, **options)
|
159
174
|
name = normalize_key(name, options)
|
160
175
|
cache = local_cache
|
161
176
|
cache.mute do
|
162
177
|
if value
|
163
178
|
cache.write(name, value, options)
|
164
179
|
else
|
165
|
-
cache.delete(name, options)
|
180
|
+
cache.delete(name, **options)
|
166
181
|
end
|
167
182
|
end
|
168
183
|
end
|
@@ -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
|