activesupport 7.1.1 → 7.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +104 -0
- data/lib/active_support/broadcast_logger.rb +8 -0
- data/lib/active_support/cache/entry.rb +7 -1
- data/lib/active_support/cache/file_store.rb +1 -1
- data/lib/active_support/cache/mem_cache_store.rb +16 -8
- data/lib/active_support/cache/memory_store.rb +4 -4
- data/lib/active_support/cache/redis_cache_store.rb +21 -14
- data/lib/active_support/cache/strategy/local_cache.rb +9 -6
- data/lib/active_support/cache.rb +34 -7
- data/lib/active_support/core_ext/date/conversions.rb +1 -1
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/deprecation/behaviors.rb +18 -16
- data/lib/active_support/deprecation/reporting.rb +7 -4
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/inflector/methods.rb +2 -2
- data/lib/active_support/json/encoding.rb +1 -1
- data/lib/active_support/log_subscriber.rb +8 -2
- data/lib/active_support/messages/metadata.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +25 -19
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
- data/lib/active_support/number_helper.rb +379 -318
- data/lib/active_support/ordered_options.rb +2 -2
- data/lib/active_support/syntax_error_proxy.rb +22 -1
- data/lib/active_support/testing/assertions.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +1 -0
- data/lib/active_support/testing/time_helpers.rb +5 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5694cfb6b4f9606e418f0719251eddccf4ddb2db2747a3965d22e204d7d53da3
|
4
|
+
data.tar.gz: fb6419c22aa79734268b1c3435692cf6e9e7e18a0522d4089f1528a4f401edb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84e38bfcc73526a4f62531d6387a57e235f211112dc65f4dd436a32c6cf88aceaa40990d29cb49612c4458d4768036bb1315cb96265109c029a4faed65fb6e02
|
7
|
+
data.tar.gz: 0f0a733d3dcf357ebee24484b1c9832f55b22e362328a537d2d6ee3afe4996e5c880d6ebb78bd90c4e1a7139a75dfcfdaef7bbba06289d90d213ed0dcbfc6abe
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,107 @@
|
|
1
|
+
## Rails 7.1.3 (January 16, 2024) ##
|
2
|
+
|
3
|
+
* Handle nil `backtrace_locations` in `ActiveSupport::SyntaxErrorProxy`.
|
4
|
+
|
5
|
+
*Eugene Kenny*
|
6
|
+
|
7
|
+
* Fix `ActiveSupport::JSON.encode` to prevent duplicate keys.
|
8
|
+
|
9
|
+
If the same key exist in both String and Symbol form it could
|
10
|
+
lead to the same key being emitted twice.
|
11
|
+
|
12
|
+
*Manish Sharma*
|
13
|
+
|
14
|
+
* Fix `ActiveSupport::Cache::Store#read_multi` when using a cache namespace
|
15
|
+
and local cache strategy.
|
16
|
+
|
17
|
+
*Mark Oleson*
|
18
|
+
|
19
|
+
* Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
|
20
|
+
|
21
|
+
There is a bug in the current implementation of #travel_to:
|
22
|
+
it remembers a timezone of its argument, and all stubbed methods start
|
23
|
+
returning results in that remembered timezone. However, the expected
|
24
|
+
behaviour is to return results in a system timezone.
|
25
|
+
|
26
|
+
*Aleksei Chernenkov*
|
27
|
+
|
28
|
+
* Fix `:unless_exist` option for `MemoryStore#write` (et al) when using a
|
29
|
+
cache namespace.
|
30
|
+
|
31
|
+
*S. Brent Faulkner*
|
32
|
+
|
33
|
+
* Fix ActiveSupport::Deprecation to handle blaming generated code.
|
34
|
+
|
35
|
+
*Jean Boussier*, *fatkodima*
|
36
|
+
|
37
|
+
|
38
|
+
## Rails 7.1.2 (November 10, 2023) ##
|
39
|
+
|
40
|
+
* Fix `:expires_in` option for `RedisCacheStore#write_multi`.
|
41
|
+
|
42
|
+
*fatkodima*
|
43
|
+
|
44
|
+
* Fix deserialization of non-string "purpose" field in Message serializer
|
45
|
+
|
46
|
+
*Jacopo Beschi*
|
47
|
+
|
48
|
+
* Prevent global cache options being overwritten when setting dynamic options
|
49
|
+
inside a `ActiveSupport::Cache::Store#fetch` block.
|
50
|
+
|
51
|
+
*Yasha Krasnou*
|
52
|
+
|
53
|
+
* Fix missing `require` resulting in `NoMethodError` when running
|
54
|
+
`bin/rails secrets:show` or `bin/rails secrets:edit`.
|
55
|
+
|
56
|
+
*Stephen Ierodiaconou*
|
57
|
+
|
58
|
+
* Ensure `{down,up}case_first` returns non-frozen string.
|
59
|
+
|
60
|
+
*Jonathan Hefner*
|
61
|
+
|
62
|
+
* Fix `#to_fs(:human_size)` to correctly work with negative numbers.
|
63
|
+
|
64
|
+
*Earlopain*
|
65
|
+
|
66
|
+
* Fix `BroadcastLogger#dup` so that it duplicates the logger's `broadcasts`.
|
67
|
+
|
68
|
+
*Andrew Novoselac*
|
69
|
+
|
70
|
+
* Fix issue where `bootstrap.rb` overwrites the `level` of a `BroadcastLogger`'s `broadcasts`.
|
71
|
+
|
72
|
+
*Andrew Novoselac*
|
73
|
+
|
74
|
+
* Fix `ActiveSupport::Cache` to handle outdated Marshal payload from Rails 6.1 format.
|
75
|
+
|
76
|
+
Active Support's Cache is supposed to treat a Marshal payload that can no longer be
|
77
|
+
deserialized as a cache miss. It fail to do so for compressed payload in the Rails 6.1
|
78
|
+
legacy format.
|
79
|
+
|
80
|
+
*Jean Boussier*
|
81
|
+
|
82
|
+
* Fix `OrderedOptions#dig` for array indexes.
|
83
|
+
|
84
|
+
*fatkodima*
|
85
|
+
|
86
|
+
* Fix time travel helpers to work when nested using with separate classes.
|
87
|
+
|
88
|
+
*fatkodima*
|
89
|
+
|
90
|
+
* Fix `delete_matched` for file cache store to work with keys longer than the
|
91
|
+
max filename size.
|
92
|
+
|
93
|
+
*fatkodima* and *Jonathan Hefner*
|
94
|
+
|
95
|
+
* Fix compatibility with the `semantic_logger` gem.
|
96
|
+
|
97
|
+
The `semantic_logger` gem doesn't behave exactly like stdlib logger in that
|
98
|
+
`SemanticLogger#level` returns a Symbol while stdlib `Logger#level` returns an Integer.
|
99
|
+
|
100
|
+
This caused the various `LogSubscriber` classes in Rails to break when assigned a
|
101
|
+
`SemanticLogger` instance.
|
102
|
+
|
103
|
+
*Jean Boussier*, *ojab*
|
104
|
+
|
1
105
|
## Rails 7.1.1 (October 11, 2023) ##
|
2
106
|
|
3
107
|
* Add support for keyword arguments when delegating calls to custom loggers from `ActiveSupport::BroadcastLogger`.
|
@@ -218,6 +218,14 @@ module ActiveSupport
|
|
218
218
|
dispatch { |logger| logger.fatal! }
|
219
219
|
end
|
220
220
|
|
221
|
+
def initialize_copy(other)
|
222
|
+
@broadcasts = []
|
223
|
+
@progname = other.progname.dup
|
224
|
+
@formatter = other.formatter.dup
|
225
|
+
|
226
|
+
broadcast_to(*other.broadcasts.map(&:dup))
|
227
|
+
end
|
228
|
+
|
221
229
|
private
|
222
230
|
def dispatch(&block)
|
223
231
|
@broadcasts.each { |logger| block.call(logger) }
|
@@ -121,7 +121,13 @@ module ActiveSupport
|
|
121
121
|
|
122
122
|
private
|
123
123
|
def uncompress(value)
|
124
|
-
|
124
|
+
marshal_load(Zlib::Inflate.inflate(value))
|
125
|
+
end
|
126
|
+
|
127
|
+
def marshal_load(payload)
|
128
|
+
Marshal.load(payload)
|
129
|
+
rescue ArgumentError => error
|
130
|
+
raise Cache::DeserializationError, error.message
|
125
131
|
end
|
126
132
|
end
|
127
133
|
end
|
@@ -176,7 +176,7 @@ module ActiveSupport
|
|
176
176
|
|
177
177
|
# Translate a file path into a key.
|
178
178
|
def file_path_key(path)
|
179
|
-
fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last
|
179
|
+
fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last.delete(File::SEPARATOR)
|
180
180
|
URI.decode_www_form_component(fname, Encoding::UTF_8)
|
181
181
|
end
|
182
182
|
|
@@ -24,11 +24,11 @@ module ActiveSupport
|
|
24
24
|
#
|
25
25
|
# Special features:
|
26
26
|
# - Clustering and load balancing. One can specify multiple memcached servers,
|
27
|
-
# and MemCacheStore will load balance between all available servers. If a
|
28
|
-
# server goes down, then MemCacheStore will ignore it until it comes back up.
|
27
|
+
# and +MemCacheStore+ will load balance between all available servers. If a
|
28
|
+
# server goes down, then +MemCacheStore+ will ignore it until it comes back up.
|
29
29
|
#
|
30
|
-
# MemCacheStore implements the Strategy::LocalCache strategy which
|
31
|
-
# an in-memory cache inside of a block.
|
30
|
+
# +MemCacheStore+ implements the Strategy::LocalCache strategy which
|
31
|
+
# implements an in-memory cache inside of a block.
|
32
32
|
class MemCacheStore < Store
|
33
33
|
# These options represent behavior overridden by this implementation and should
|
34
34
|
# not be allowed to get down to the Dalli client
|
@@ -106,14 +106,14 @@ module ActiveSupport
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
# Creates a new MemCacheStore object, with the given memcached server
|
109
|
+
# Creates a new +MemCacheStore+ object, with the given memcached server
|
110
110
|
# addresses. Each address is either a host name, or a host-with-port string
|
111
111
|
# in the form of "host_name:port". For example:
|
112
112
|
#
|
113
113
|
# ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
|
114
114
|
#
|
115
115
|
# If no addresses are provided, but <tt>ENV['MEMCACHE_SERVERS']</tt> is defined, it will be used instead. Otherwise,
|
116
|
-
# MemCacheStore will connect to localhost:11211 (the default memcached port).
|
116
|
+
# +MemCacheStore+ will connect to localhost:11211 (the default memcached port).
|
117
117
|
# Passing a +Dalli::Client+ instance is deprecated and will be removed. Please pass an address instead.
|
118
118
|
def initialize(*addresses)
|
119
119
|
addresses = addresses.flatten
|
@@ -270,14 +270,22 @@ module ActiveSupport
|
|
270
270
|
def read_multi_entries(names, **options)
|
271
271
|
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
272
272
|
|
273
|
-
raw_values =
|
273
|
+
raw_values = begin
|
274
|
+
@data.with { |c| c.get_multi(keys_to_names.keys) }
|
275
|
+
rescue Dalli::UnmarshalError
|
276
|
+
{}
|
277
|
+
end
|
278
|
+
|
274
279
|
values = {}
|
275
280
|
|
276
281
|
raw_values.each do |key, value|
|
277
282
|
entry = deserialize_entry(value, raw: options[:raw])
|
278
283
|
|
279
284
|
unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
|
280
|
-
|
285
|
+
begin
|
286
|
+
values[keys_to_names[key]] = entry.value
|
287
|
+
rescue DeserializationError
|
288
|
+
end
|
281
289
|
end
|
282
290
|
end
|
283
291
|
|
@@ -18,13 +18,13 @@ module ActiveSupport
|
|
18
18
|
# a cleanup will occur which tries to prune the cache down to three quarters
|
19
19
|
# of the maximum size by removing the least recently used entries.
|
20
20
|
#
|
21
|
-
# Unlike other Cache store implementations, MemoryStore does not compress
|
22
|
-
# values by default. MemoryStore does not benefit from compression as much
|
21
|
+
# Unlike other Cache store implementations, +MemoryStore+ does not compress
|
22
|
+
# values by default. +MemoryStore+ does not benefit from compression as much
|
23
23
|
# as other Store implementations, as it does not send data over a network.
|
24
24
|
# However, when compression is enabled, it still pays the full cost of
|
25
25
|
# compression in terms of cpu use.
|
26
26
|
#
|
27
|
-
# MemoryStore is thread-safe.
|
27
|
+
# +MemoryStore+ is thread-safe.
|
28
28
|
class MemoryStore < Store
|
29
29
|
module DupCoder # :nodoc:
|
30
30
|
extend self
|
@@ -209,7 +209,7 @@ module ActiveSupport
|
|
209
209
|
def write_entry(key, entry, **options)
|
210
210
|
payload = serialize_entry(entry, **options)
|
211
211
|
synchronize do
|
212
|
-
return false if options[:unless_exist] && exist?(key)
|
212
|
+
return false if options[:unless_exist] && exist?(key, namespace: nil)
|
213
213
|
|
214
214
|
old_payload = @data[key]
|
215
215
|
if old_payload
|
@@ -19,22 +19,23 @@ module ActiveSupport
|
|
19
19
|
module Cache
|
20
20
|
# = Redis \Cache \Store
|
21
21
|
#
|
22
|
-
# Deployment note: Take care to use a
|
23
|
-
# than pointing this at
|
24
|
-
#
|
22
|
+
# Deployment note: Take care to use a <b>dedicated Redis cache</b> rather
|
23
|
+
# than pointing this at a persistent Redis server (for example, one used as
|
24
|
+
# an Active Job queue). Redis won't cope well with mixed usage patterns and it
|
25
|
+
# won't expire cache entries by default.
|
25
26
|
#
|
26
27
|
# Redis cache server setup guide: https://redis.io/topics/lru-cache
|
27
28
|
#
|
28
|
-
# * Supports vanilla Redis, hiredis, and Redis::Distributed
|
29
|
-
# * Supports Memcached-like sharding across Redises with Redis::Distributed
|
29
|
+
# * Supports vanilla Redis, hiredis, and +Redis::Distributed+.
|
30
|
+
# * Supports Memcached-like sharding across Redises with +Redis::Distributed+.
|
30
31
|
# * Fault tolerant. If the Redis server is unavailable, no exceptions are
|
31
32
|
# raised. Cache fetches are all misses and writes are dropped.
|
32
33
|
# * Local cache. Hot in-memory primary cache within block/middleware scope.
|
33
|
-
# * +read_multi+ and +write_multi+ support for Redis mget/mset. Use
|
34
|
-
# 4.0.1+ for distributed mget support.
|
34
|
+
# * +read_multi+ and +write_multi+ support for Redis mget/mset. Use
|
35
|
+
# +Redis::Distributed+ 4.0.1+ for distributed mget support.
|
35
36
|
# * +delete_matched+ support for Redis KEYS globs.
|
36
37
|
class RedisCacheStore < Store
|
37
|
-
# Keys are truncated with the
|
38
|
+
# Keys are truncated with the Active Support digest if they exceed 1kB
|
38
39
|
MAX_KEY_BYTESIZE = 1024
|
39
40
|
|
40
41
|
DEFAULT_REDIS_OPTIONS = {
|
@@ -110,8 +111,11 @@ module ActiveSupport
|
|
110
111
|
|
111
112
|
# Creates a new Redis cache store.
|
112
113
|
#
|
113
|
-
#
|
114
|
-
#
|
114
|
+
# There are four ways to provide the Redis client used by the cache: the
|
115
|
+
# +:redis+ param can be a Redis instance or a block that returns a Redis
|
116
|
+
# instance, or the +:url+ param can be a string or an array of strings
|
117
|
+
# which will be used to create a Redis instance or a +Redis::Distributed+
|
118
|
+
# instance.
|
115
119
|
#
|
116
120
|
# Option Class Result
|
117
121
|
# :redis Proc -> options[:redis].call
|
@@ -134,7 +138,7 @@ module ActiveSupport
|
|
134
138
|
#
|
135
139
|
# Race condition TTL is not set by default. This can be used to avoid
|
136
140
|
# "thundering herd" cache writes when hot cache entries are expired.
|
137
|
-
# See
|
141
|
+
# See ActiveSupport::Cache::Store#fetch for more.
|
138
142
|
#
|
139
143
|
# Setting <tt>skip_nil: true</tt> will not cache nil results:
|
140
144
|
#
|
@@ -242,7 +246,7 @@ module ActiveSupport
|
|
242
246
|
# Decrement a cached integer value using the Redis decrby atomic operator.
|
243
247
|
# Returns the updated value.
|
244
248
|
#
|
245
|
-
# If the key is unset or has expired, it will be set to
|
249
|
+
# If the key is unset or has expired, it will be set to +-amount+:
|
246
250
|
#
|
247
251
|
# cache.decrement("foo") # => -1
|
248
252
|
#
|
@@ -332,7 +336,10 @@ module ActiveSupport
|
|
332
336
|
if value
|
333
337
|
entry = deserialize_entry(value, raw: raw)
|
334
338
|
unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(name, options))
|
335
|
-
|
339
|
+
begin
|
340
|
+
results[name] = entry.value
|
341
|
+
rescue DeserializationError
|
342
|
+
end
|
336
343
|
end
|
337
344
|
end
|
338
345
|
end
|
@@ -383,7 +390,7 @@ module ActiveSupport
|
|
383
390
|
end
|
384
391
|
|
385
392
|
# Nonstandard store provider API to write multiple values at once.
|
386
|
-
def write_multi_entries(entries,
|
393
|
+
def write_multi_entries(entries, **options)
|
387
394
|
return if entries.empty?
|
388
395
|
|
389
396
|
failsafe :write_multi_entries do
|
@@ -131,17 +131,20 @@ module ActiveSupport
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
def read_multi_entries(
|
134
|
+
def read_multi_entries(names, **options)
|
135
135
|
return super unless local_cache
|
136
136
|
|
137
|
-
|
137
|
+
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
138
|
+
|
139
|
+
local_entries = local_cache.read_multi_entries(keys_to_names.keys)
|
140
|
+
local_entries.transform_keys! { |key| keys_to_names[key] }
|
138
141
|
local_entries.transform_values! do |payload|
|
139
|
-
deserialize_entry(payload)&.value
|
142
|
+
deserialize_entry(payload, **options)&.value
|
140
143
|
end
|
141
|
-
|
144
|
+
missed_names = names - local_entries.keys
|
142
145
|
|
143
|
-
if
|
144
|
-
local_entries.merge!(super(
|
146
|
+
if missed_names.any?
|
147
|
+
local_entries.merge!(super(missed_names, **options))
|
145
148
|
else
|
146
149
|
local_entries
|
147
150
|
end
|
data/lib/active_support/cache.rb
CHANGED
@@ -160,8 +160,8 @@ module ActiveSupport
|
|
160
160
|
# Some implementations may not support all methods beyond the basic cache
|
161
161
|
# methods of #fetch, #write, #read, #exist?, and #delete.
|
162
162
|
#
|
163
|
-
# ActiveSupport::Cache::Store can store any Ruby object that is supported
|
164
|
-
# its +coder+'s +dump+ and +load+ methods.
|
163
|
+
# +ActiveSupport::Cache::Store+ can store any Ruby object that is supported
|
164
|
+
# by its +coder+'s +dump+ and +load+ methods.
|
165
165
|
#
|
166
166
|
# cache = ActiveSupport::Cache::MemoryStore.new
|
167
167
|
#
|
@@ -370,8 +370,8 @@ module ActiveSupport
|
|
370
370
|
#
|
371
371
|
# ==== Options
|
372
372
|
#
|
373
|
-
# Internally, +fetch+ calls
|
374
|
-
# miss. Thus, +fetch+ supports the same options as #read and #write.
|
373
|
+
# Internally, +fetch+ calls +read_entry+, and calls +write_entry+ on a
|
374
|
+
# cache miss. Thus, +fetch+ supports the same options as #read and #write.
|
375
375
|
# Additionally, +fetch+ supports the following options:
|
376
376
|
#
|
377
377
|
# * <tt>force: true</tt> - Forces a cache "miss," meaning we treat the
|
@@ -459,7 +459,17 @@ module ActiveSupport
|
|
459
459
|
instrument(:read, name, options) do |payload|
|
460
460
|
cached_entry = read_entry(key, **options, event: payload)
|
461
461
|
entry = handle_expired_entry(cached_entry, key, options)
|
462
|
-
|
462
|
+
if entry
|
463
|
+
if entry.mismatched?(normalize_version(name, options))
|
464
|
+
entry = nil
|
465
|
+
else
|
466
|
+
begin
|
467
|
+
entry.value
|
468
|
+
rescue DeserializationError
|
469
|
+
entry = nil
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
463
473
|
payload[:super_operation] = :fetch if payload
|
464
474
|
payload[:hit] = !!entry if payload
|
465
475
|
end
|
@@ -511,7 +521,12 @@ module ActiveSupport
|
|
511
521
|
nil
|
512
522
|
else
|
513
523
|
payload[:hit] = true if payload
|
514
|
-
|
524
|
+
begin
|
525
|
+
entry.value
|
526
|
+
rescue DeserializationError
|
527
|
+
payload[:hit] = false
|
528
|
+
nil
|
529
|
+
end
|
515
530
|
end
|
516
531
|
else
|
517
532
|
payload[:hit] = false if payload
|
@@ -803,7 +818,7 @@ module ActiveSupport
|
|
803
818
|
end
|
804
819
|
end
|
805
820
|
|
806
|
-
def deserialize_entry(payload)
|
821
|
+
def deserialize_entry(payload, **)
|
807
822
|
payload.nil? ? nil : @coder.load(payload)
|
808
823
|
rescue DeserializationError
|
809
824
|
nil
|
@@ -1038,6 +1053,8 @@ module ActiveSupport
|
|
1038
1053
|
end
|
1039
1054
|
|
1040
1055
|
def save_block_result_to_cache(name, options)
|
1056
|
+
options = options.dup
|
1057
|
+
|
1041
1058
|
result = instrument(:generate, name, options) do
|
1042
1059
|
yield(name, WriteOptions.new(options))
|
1043
1060
|
end
|
@@ -1047,6 +1064,10 @@ module ActiveSupport
|
|
1047
1064
|
end
|
1048
1065
|
end
|
1049
1066
|
|
1067
|
+
# Enables the dynamic configuration of Cache entry options while ensuring
|
1068
|
+
# that conflicting options are not both set. When a block is given to
|
1069
|
+
# ActiveSupport::Cache::Store#fetch, the second argument will be an
|
1070
|
+
# instance of +WriteOptions+.
|
1050
1071
|
class WriteOptions
|
1051
1072
|
def initialize(options) # :nodoc:
|
1052
1073
|
@options = options
|
@@ -1064,6 +1085,9 @@ module ActiveSupport
|
|
1064
1085
|
@options[:expires_in]
|
1065
1086
|
end
|
1066
1087
|
|
1088
|
+
# Sets the Cache entry's +expires_in+ value. If an +expires_at+ option was
|
1089
|
+
# previously set, this will unset it since +expires_in+ and +expires_at+
|
1090
|
+
# cannot both be set.
|
1067
1091
|
def expires_in=(expires_in)
|
1068
1092
|
@options.delete(:expires_at)
|
1069
1093
|
@options[:expires_in] = expires_in
|
@@ -1073,6 +1097,9 @@ module ActiveSupport
|
|
1073
1097
|
@options[:expires_at]
|
1074
1098
|
end
|
1075
1099
|
|
1100
|
+
# Sets the Cache entry's +expires_at+ value. If an +expires_in+ option was
|
1101
|
+
# previously set, this will unset it since +expires_at+ and +expires_in+
|
1102
|
+
# cannot both be set.
|
1076
1103
|
def expires_at=(expires_at)
|
1077
1104
|
@options.delete(:expires_in)
|
1078
1105
|
@options[:expires_at] = expires_at
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "active_support/concern"
|
4
4
|
|
5
5
|
class Module
|
6
|
-
#
|
6
|
+
# == Bite-sized separation of concerns
|
7
7
|
#
|
8
8
|
# We often find ourselves with a medium-sized chunk of behavior that we'd
|
9
9
|
# like to extract, but only mix in to a single class.
|
@@ -18,9 +18,9 @@ class Module
|
|
18
18
|
# with a comment, as a least-bad alternative. Using modules in separate files
|
19
19
|
# means tedious sifting to get a big-picture view.
|
20
20
|
#
|
21
|
-
#
|
21
|
+
# == Dissatisfying ways to separate small concerns
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# === Using comments:
|
24
24
|
#
|
25
25
|
# class Todo < ApplicationRecord
|
26
26
|
# # Other todo implementation
|
@@ -37,7 +37,7 @@ class Module
|
|
37
37
|
# end
|
38
38
|
# end
|
39
39
|
#
|
40
|
-
#
|
40
|
+
# === With an inline module:
|
41
41
|
#
|
42
42
|
# Noisy syntax.
|
43
43
|
#
|
@@ -61,7 +61,7 @@ class Module
|
|
61
61
|
# include EventTracking
|
62
62
|
# end
|
63
63
|
#
|
64
|
-
#
|
64
|
+
# === Mix-in noise exiled to its own file:
|
65
65
|
#
|
66
66
|
# Once our chunk of behavior starts pushing the scroll-to-understand-it
|
67
67
|
# boundary, we give in and move it to a separate file. At this size, the
|
@@ -75,7 +75,7 @@ class Module
|
|
75
75
|
# include TodoEventTracking
|
76
76
|
# end
|
77
77
|
#
|
78
|
-
#
|
78
|
+
# == Introducing Module#concerning
|
79
79
|
#
|
80
80
|
# By quieting the mix-in noise, we arrive at a natural, low-ceremony way to
|
81
81
|
# separate bite-sized concerns.
|
@@ -68,7 +68,7 @@ class Object
|
|
68
68
|
# You can access these methods using the class name instead:
|
69
69
|
#
|
70
70
|
# class Phone < ActiveRecord::Base
|
71
|
-
# enum phone_number_type
|
71
|
+
# enum :phone_number_type, { home: 0, office: 1, mobile: 2 }
|
72
72
|
#
|
73
73
|
# with_options presence: true do
|
74
74
|
# validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
|
@@ -24,7 +24,7 @@ class String
|
|
24
24
|
#
|
25
25
|
# The second argument, +indent_string+, specifies which indent string to
|
26
26
|
# use. The default is +nil+, which tells the method to make a guess by
|
27
|
-
# peeking at the first indented line, and
|
27
|
+
# peeking at the first indented line, and fall back to a space if there is
|
28
28
|
# none.
|
29
29
|
#
|
30
30
|
# " foo".indent(2) # => " foo"
|
@@ -57,15 +57,15 @@ module ActiveSupport
|
|
57
57
|
# You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+
|
58
58
|
# constant. Available behaviors are:
|
59
59
|
#
|
60
|
-
# [
|
61
|
-
# [
|
62
|
-
# [
|
63
|
-
# [
|
64
|
-
# [
|
65
|
-
# [
|
60
|
+
# [+:raise+] Raise ActiveSupport::DeprecationException.
|
61
|
+
# [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
|
62
|
+
# [+:log+] Log all deprecation warnings to +Rails.logger+.
|
63
|
+
# [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
|
64
|
+
# [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
|
65
|
+
# [+:silence+] Do nothing. On \Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
|
66
66
|
#
|
67
67
|
# Setting behaviors only affects deprecations that happen after boot time.
|
68
|
-
# For more information you can read the documentation of the
|
68
|
+
# For more information you can read the documentation of the #behavior= method.
|
69
69
|
module Behavior
|
70
70
|
# Whether to print a backtrace along with the warning.
|
71
71
|
attr_accessor :debug
|
@@ -85,12 +85,12 @@ module ActiveSupport
|
|
85
85
|
#
|
86
86
|
# Available behaviors:
|
87
87
|
#
|
88
|
-
# [
|
89
|
-
# [
|
90
|
-
# [
|
91
|
-
# [
|
92
|
-
# [
|
93
|
-
# [
|
88
|
+
# [+:raise+] Raise ActiveSupport::DeprecationException.
|
89
|
+
# [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
|
90
|
+
# [+:log+] Log all deprecation warnings to +Rails.logger+.
|
91
|
+
# [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
|
92
|
+
# [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
|
93
|
+
# [+:silence+] Do nothing.
|
94
94
|
#
|
95
95
|
# Setting behaviors only affects deprecations that happen after boot time.
|
96
96
|
# Deprecation warnings raised by gems are not affected by this setting
|
@@ -104,15 +104,17 @@ module ActiveSupport
|
|
104
104
|
# # custom stuff
|
105
105
|
# }
|
106
106
|
#
|
107
|
-
# If you are using \Rails, you can set
|
108
|
-
#
|
107
|
+
# If you are using \Rails, you can set
|
108
|
+
# <tt>config.active_support.report_deprecations = false</tt> to disable
|
109
|
+
# all deprecation behaviors. This is similar to the +:silence+ option but
|
110
|
+
# more performant.
|
109
111
|
def behavior=(behavior)
|
110
112
|
@behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
|
111
113
|
end
|
112
114
|
|
113
115
|
# Sets the behavior for disallowed deprecations (those configured by
|
114
116
|
# ActiveSupport::Deprecation#disallowed_warnings=) to the specified
|
115
|
-
# value. As with
|
117
|
+
# value. As with #behavior=, this can be a single value, array, or an
|
116
118
|
# object that responds to +call+.
|
117
119
|
def disallowed_behavior=(behavior)
|
118
120
|
@disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
|
@@ -142,7 +142,9 @@ module ActiveSupport
|
|
142
142
|
return _extract_callstack(callstack) if callstack.first.is_a? String
|
143
143
|
|
144
144
|
offending_line = callstack.find { |frame|
|
145
|
-
|
145
|
+
# Code generated with `eval` doesn't have an `absolute_path`, e.g. templates.
|
146
|
+
path = frame.absolute_path || frame.path
|
147
|
+
path && !ignored_callstack?(path)
|
146
148
|
} || callstack.first
|
147
149
|
|
148
150
|
[offending_line.path, offending_line.lineno, offending_line.label]
|
@@ -150,7 +152,7 @@ module ActiveSupport
|
|
150
152
|
|
151
153
|
def _extract_callstack(callstack)
|
152
154
|
warn "Please pass `caller_locations` to the deprecation API" if $VERBOSE
|
153
|
-
offending_line = callstack.find { |line| !ignored_callstack(line) } || callstack.first
|
155
|
+
offending_line = callstack.find { |line| !ignored_callstack?(line) } || callstack.first
|
154
156
|
|
155
157
|
if offending_line
|
156
158
|
if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
|
@@ -162,9 +164,10 @@ module ActiveSupport
|
|
162
164
|
end
|
163
165
|
|
164
166
|
RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/"
|
167
|
+
LIB_DIR = RbConfig::CONFIG["libdir"]
|
165
168
|
|
166
|
-
def ignored_callstack(path)
|
167
|
-
path.start_with?(RAILS_GEM_ROOT
|
169
|
+
def ignored_callstack?(path)
|
170
|
+
path.start_with?(RAILS_GEM_ROOT, LIB_DIR)
|
168
171
|
end
|
169
172
|
end
|
170
173
|
end
|
@@ -164,7 +164,7 @@ module ActiveSupport
|
|
164
164
|
# upcase_first('w') # => "W"
|
165
165
|
# upcase_first('') # => ""
|
166
166
|
def upcase_first(string)
|
167
|
-
string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
|
167
|
+
string.length > 0 ? string[0].upcase.concat(string[1..-1]) : +""
|
168
168
|
end
|
169
169
|
|
170
170
|
# Converts the first character in the string to lowercase.
|
@@ -173,7 +173,7 @@ module ActiveSupport
|
|
173
173
|
# downcase_first('I') # => "i"
|
174
174
|
# downcase_first('') # => ""
|
175
175
|
def downcase_first(string)
|
176
|
-
string.length > 0 ? string[0].downcase.concat(string[1..-1]) : ""
|
176
|
+
string.length > 0 ? string[0].downcase.concat(string[1..-1]) : +""
|
177
177
|
end
|
178
178
|
|
179
179
|
# Capitalizes all the words and replaces some characters in the string to
|