activesupport 7.1.2 → 7.1.3.4
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 +57 -0
- data/lib/active_support/cache/mem_cache_store.rb +6 -6
- data/lib/active_support/cache/memory_store.rb +4 -4
- data/lib/active_support/cache/redis_cache_store.rb +16 -12
- data/lib/active_support/cache/strategy/local_cache.rb +9 -6
- data/lib/active_support/cache.rb +15 -5
- 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 +2 -2
- data/lib/active_support/html_safe_translation.rb +12 -2
- data/lib/active_support/json/encoding.rb +1 -1
- data/lib/active_support/number_helper.rb +379 -318
- data/lib/active_support/syntax_error_proxy.rb +22 -1
- data/lib/active_support/testing/assertions.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +4 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63e4b9598ffeea57d9aa5ab27deb5249cc21324883d53ad536bb02fd5d8e4526
|
4
|
+
data.tar.gz: 82041b4d7a4b287404280f004cc9a255ad55ec975682ceb4829be789bce352bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0e517fefe56838a7851ec1832ea1cb9fbc10aa392da9f3840ee7d71b0768d29825e03176b5358a5e098ed42686d0602bd13ebb08a750e6294992fb3ac845555
|
7
|
+
data.tar.gz: d58c4664ef7962fab547b4d5dc91e7cca0ac647b0b4e080c49129c06ca9d0604dc7d4ee2f9e0347a1100d435789923aafb94adfa49c6cb7f031e18b1e44d798f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,60 @@
|
|
1
|
+
## Rails 7.1.3.4 (June 04, 2024) ##
|
2
|
+
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
|
6
|
+
## Rails 7.1.3.3 (May 16, 2024) ##
|
7
|
+
|
8
|
+
* No changes.
|
9
|
+
|
10
|
+
|
11
|
+
## Rails 7.1.3.2 (February 21, 2024) ##
|
12
|
+
|
13
|
+
* No changes.
|
14
|
+
|
15
|
+
|
16
|
+
## Rails 7.1.3.1 (February 21, 2024) ##
|
17
|
+
|
18
|
+
* No changes.
|
19
|
+
|
20
|
+
|
21
|
+
## Rails 7.1.3 (January 16, 2024) ##
|
22
|
+
|
23
|
+
* Handle nil `backtrace_locations` in `ActiveSupport::SyntaxErrorProxy`.
|
24
|
+
|
25
|
+
*Eugene Kenny*
|
26
|
+
|
27
|
+
* Fix `ActiveSupport::JSON.encode` to prevent duplicate keys.
|
28
|
+
|
29
|
+
If the same key exist in both String and Symbol form it could
|
30
|
+
lead to the same key being emitted twice.
|
31
|
+
|
32
|
+
*Manish Sharma*
|
33
|
+
|
34
|
+
* Fix `ActiveSupport::Cache::Store#read_multi` when using a cache namespace
|
35
|
+
and local cache strategy.
|
36
|
+
|
37
|
+
*Mark Oleson*
|
38
|
+
|
39
|
+
* Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
|
40
|
+
|
41
|
+
There is a bug in the current implementation of #travel_to:
|
42
|
+
it remembers a timezone of its argument, and all stubbed methods start
|
43
|
+
returning results in that remembered timezone. However, the expected
|
44
|
+
behaviour is to return results in a system timezone.
|
45
|
+
|
46
|
+
*Aleksei Chernenkov*
|
47
|
+
|
48
|
+
* Fix `:unless_exist` option for `MemoryStore#write` (et al) when using a
|
49
|
+
cache namespace.
|
50
|
+
|
51
|
+
*S. Brent Faulkner*
|
52
|
+
|
53
|
+
* Fix ActiveSupport::Deprecation to handle blaming generated code.
|
54
|
+
|
55
|
+
*Jean Boussier*, *fatkodima*
|
56
|
+
|
57
|
+
|
1
58
|
## Rails 7.1.2 (November 10, 2023) ##
|
2
59
|
|
3
60
|
* Fix `:expires_in` option for `RedisCacheStore#write_multi`.
|
@@ -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
|
@@ -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
|
#
|
@@ -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
|
@@ -818,7 +818,7 @@ module ActiveSupport
|
|
818
818
|
end
|
819
819
|
end
|
820
820
|
|
821
|
-
def deserialize_entry(payload)
|
821
|
+
def deserialize_entry(payload, **)
|
822
822
|
payload.nil? ? nil : @coder.load(payload)
|
823
823
|
rescue DeserializationError
|
824
824
|
nil
|
@@ -1064,6 +1064,10 @@ module ActiveSupport
|
|
1064
1064
|
end
|
1065
1065
|
end
|
1066
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+.
|
1067
1071
|
class WriteOptions
|
1068
1072
|
def initialize(options) # :nodoc:
|
1069
1073
|
@options = options
|
@@ -1081,6 +1085,9 @@ module ActiveSupport
|
|
1081
1085
|
@options[:expires_in]
|
1082
1086
|
end
|
1083
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.
|
1084
1091
|
def expires_in=(expires_in)
|
1085
1092
|
@options.delete(:expires_at)
|
1086
1093
|
@options[:expires_in] = expires_in
|
@@ -1090,6 +1097,9 @@ module ActiveSupport
|
|
1090
1097
|
@options[:expires_at]
|
1091
1098
|
end
|
1092
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.
|
1093
1103
|
def expires_at=(expires_at)
|
1094
1104
|
@options.delete(:expires_in)
|
1095
1105
|
@options[:expires_at] = expires_at
|
@@ -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
|
@@ -7,8 +7,18 @@ module ActiveSupport
|
|
7
7
|
def translate(key, **options)
|
8
8
|
if html_safe_translation_key?(key)
|
9
9
|
html_safe_options = html_escape_translation_options(options)
|
10
|
-
|
11
|
-
|
10
|
+
|
11
|
+
exception = false
|
12
|
+
exception_handler = ->(*args) do
|
13
|
+
exception = true
|
14
|
+
I18n.exception_handler.call(*args)
|
15
|
+
end
|
16
|
+
translation = I18n.translate(key, **html_safe_options, exception_handler: exception_handler)
|
17
|
+
if exception
|
18
|
+
translation
|
19
|
+
else
|
20
|
+
html_safe_translation(translation)
|
21
|
+
end
|
12
22
|
else
|
13
23
|
I18n.translate(key, **options)
|
14
24
|
end
|