activesupport 8.0.1 → 8.0.2
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 +98 -0
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/broadcast_logger.rb +15 -15
- data/lib/active_support/cache/file_store.rb +2 -2
- data/lib/active_support/cache/mem_cache_store.rb +1 -1
- data/lib/active_support/cache/memory_store.rb +5 -5
- data/lib/active_support/cache/null_store.rb +2 -2
- data/lib/active_support/cache/redis_cache_store.rb +1 -1
- data/lib/active_support/cache/strategy/local_cache.rb +56 -20
- data/lib/active_support/cache.rb +2 -3
- data/lib/active_support/callbacks.rb +3 -2
- data/lib/active_support/core_ext/enumerable.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
- data/lib/active_support/core_ext/module/introspection.rb +3 -0
- data/lib/active_support/current_attributes.rb +1 -1
- data/lib/active_support/error_reporter.rb +11 -2
- data/lib/active_support/execution_wrapper.rb +1 -1
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/json/encoding.rb +23 -5
- data/lib/active_support/message_encryptors.rb +2 -2
- data/lib/active_support/message_verifier.rb +9 -0
- data/lib/active_support/message_verifiers.rb +5 -3
- data/lib/active_support/messages/rotator.rb +5 -0
- data/lib/active_support/multibyte/chars.rb +4 -1
- data/lib/active_support/railtie.rb +3 -1
- metadata +6 -10
- data/lib/active_support/testing/strict_warnings.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f094945c33f1c6e036f987c0cc7405a0146f0c800635e1fc16d8a1c34910cb7
|
4
|
+
data.tar.gz: 9ffe8729fffcae283965435a590eb7db596a43fa39c8565e814abab6e16e0444
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a391e85fc1235084e201abc2736139578767397fa4a503573e82c5f7f339e13d13b5702302ff37176a26a8d80203fc914682e40c570d933aa282e2fb92f26e76
|
7
|
+
data.tar.gz: 6adf2e0b528f17bcd51373d8e627c4ec77de8967c968fdab89fb2bac11952bf98f5ffb6910cdf372cf57bd7929f539808dc783160b0456a803783264421016ce
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,101 @@
|
|
1
|
+
## Rails 8.0.2 (March 12, 2025) ##
|
2
|
+
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
|
6
|
+
## Rails 8.0.2 (March 12, 2025) ##
|
7
|
+
|
8
|
+
* Fix setting `to_time_preserves_timezone` from `new_framework_defaults_8_0.rb`.
|
9
|
+
|
10
|
+
*fatkodima*
|
11
|
+
|
12
|
+
* Fix Active Support Cache `fetch_multi` when local store is active.
|
13
|
+
|
14
|
+
`fetch_multi` now properly yield to the provided block for missing entries
|
15
|
+
that have been recorded as such in the local store.
|
16
|
+
|
17
|
+
*Jean Boussier*
|
18
|
+
|
19
|
+
* Fix execution wrapping to report all exceptions, including `Exception`.
|
20
|
+
|
21
|
+
If a more serious error like `SystemStackError` or `NoMemoryError` happens,
|
22
|
+
the error reporter should be able to report these kinds of exceptions.
|
23
|
+
|
24
|
+
*Gannon McGibbon*
|
25
|
+
|
26
|
+
* Fix `RedisCacheStore` and `MemCacheStore` to also handle connection pool related errors.
|
27
|
+
|
28
|
+
These errors are rescued and reported to `Rails.error`.
|
29
|
+
|
30
|
+
*Jean Boussier*
|
31
|
+
|
32
|
+
* Fix `ActiveSupport::Cache#read_multi` to respect version expiry when using local cache.
|
33
|
+
|
34
|
+
*zzak*
|
35
|
+
|
36
|
+
* Fix `ActiveSupport::MessageVerifier` and `ActiveSupport::MessageEncryptor` configuration of `on_rotation` callback.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
verifier.rotate(old_secret).on_rotation { ... }
|
40
|
+
```
|
41
|
+
|
42
|
+
Now both work as documented.
|
43
|
+
|
44
|
+
*Jean Boussier*
|
45
|
+
|
46
|
+
* Fix `ActiveSupport::MessageVerifier` to always be able to verify both URL-safe and URL-unsafe payloads.
|
47
|
+
|
48
|
+
This is to allow transitioning seemlessly from either configuration without immediately invalidating
|
49
|
+
all previously generated signed messages.
|
50
|
+
|
51
|
+
*Jean Boussier*, *Florent Beaurain*, *Ali Sepehri*
|
52
|
+
|
53
|
+
* Fix `cache.fetch` to honor the provided expiry when `:race_condition_ttl` is used.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
cache.fetch("key", expires_in: 1.hour, race_condition_ttl: 5.second) do
|
57
|
+
"something"
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
In the above example, the final cache entry would have a 10 seconds TTL instead
|
62
|
+
of the requested 1 hour.
|
63
|
+
|
64
|
+
*Dhia*
|
65
|
+
|
66
|
+
* Better handle procs with splat arguments in `set_callback`.
|
67
|
+
|
68
|
+
*Radamés Roriz*
|
69
|
+
|
70
|
+
* Fix `String#mb_chars` to not mutate the receiver.
|
71
|
+
|
72
|
+
Previously it would call `force_encoding` on the receiver,
|
73
|
+
now it dups the receiver first.
|
74
|
+
|
75
|
+
*Jean Boussier*
|
76
|
+
|
77
|
+
* Improve `ErrorSubscriber` to also mark error causes as reported.
|
78
|
+
|
79
|
+
This avoid some cases of errors being reported twice, notably in views because of how
|
80
|
+
errors are wrapped in `ActionView::Template::Error`.
|
81
|
+
|
82
|
+
*Jean Boussier*
|
83
|
+
|
84
|
+
* Fix `Module#module_parent_name` to return the correct name after the module has been named.
|
85
|
+
|
86
|
+
When called on an anonymous module, the return value wouldn't change after the module was given a name
|
87
|
+
later by being assigned to a constant.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
mod = Module.new
|
91
|
+
mod.module_parent_name # => "Object"
|
92
|
+
MyModule::Something = mod
|
93
|
+
mod.module_parent_name # => "MyModule"
|
94
|
+
```
|
95
|
+
|
96
|
+
*Jean Boussier*
|
97
|
+
|
98
|
+
|
1
99
|
## Rails 8.0.1 (December 13, 2024) ##
|
2
100
|
|
3
101
|
* Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceeded by multibyte characters.
|
@@ -79,7 +79,7 @@ module ActiveSupport
|
|
79
79
|
#
|
80
80
|
# # Will turn "/my/rails/root/app/models/person.rb" into "app/models/person.rb"
|
81
81
|
# root = "#{Rails.root}/"
|
82
|
-
# backtrace_cleaner.add_filter { |line| line.
|
82
|
+
# backtrace_cleaner.add_filter { |line| line.delete_prefix(root) }
|
83
83
|
def add_filter(&block)
|
84
84
|
@filters << block
|
85
85
|
end
|
@@ -163,57 +163,57 @@ module ActiveSupport
|
|
163
163
|
dispatch { |logger| logger.close }
|
164
164
|
end
|
165
165
|
|
166
|
-
#
|
167
|
-
# to at least one broadcast.
|
166
|
+
# True if the log level allows entries with severity +Logger::DEBUG+ to be written
|
167
|
+
# to at least one broadcast. False otherwise.
|
168
168
|
def debug?
|
169
169
|
@broadcasts.any? { |logger| logger.debug? }
|
170
170
|
end
|
171
171
|
|
172
|
-
# Sets the log level to Logger::DEBUG for the whole broadcast.
|
172
|
+
# Sets the log level to +Logger::DEBUG+ for the whole broadcast.
|
173
173
|
def debug!
|
174
174
|
dispatch { |logger| logger.debug! }
|
175
175
|
end
|
176
176
|
|
177
|
-
#
|
178
|
-
# to at least one broadcast.
|
177
|
+
# True if the log level allows entries with severity +Logger::INFO+ to be written
|
178
|
+
# to at least one broadcast. False otherwise.
|
179
179
|
def info?
|
180
180
|
@broadcasts.any? { |logger| logger.info? }
|
181
181
|
end
|
182
182
|
|
183
|
-
# Sets the log level to Logger::INFO for the whole broadcast.
|
183
|
+
# Sets the log level to +Logger::INFO+ for the whole broadcast.
|
184
184
|
def info!
|
185
185
|
dispatch { |logger| logger.info! }
|
186
186
|
end
|
187
187
|
|
188
|
-
#
|
189
|
-
# to at least one broadcast.
|
188
|
+
# True if the log level allows entries with severity +Logger::WARN+ to be written
|
189
|
+
# to at least one broadcast. False otherwise.
|
190
190
|
def warn?
|
191
191
|
@broadcasts.any? { |logger| logger.warn? }
|
192
192
|
end
|
193
193
|
|
194
|
-
# Sets the log level to Logger::WARN for the whole broadcast.
|
194
|
+
# Sets the log level to +Logger::WARN+ for the whole broadcast.
|
195
195
|
def warn!
|
196
196
|
dispatch { |logger| logger.warn! }
|
197
197
|
end
|
198
198
|
|
199
|
-
#
|
200
|
-
# to at least one broadcast.
|
199
|
+
# True if the log level allows entries with severity +Logger::ERROR+ to be written
|
200
|
+
# to at least one broadcast. False otherwise.
|
201
201
|
def error?
|
202
202
|
@broadcasts.any? { |logger| logger.error? }
|
203
203
|
end
|
204
204
|
|
205
|
-
# Sets the log level to Logger::ERROR for the whole broadcast.
|
205
|
+
# Sets the log level to +Logger::ERROR+ for the whole broadcast.
|
206
206
|
def error!
|
207
207
|
dispatch { |logger| logger.error! }
|
208
208
|
end
|
209
209
|
|
210
|
-
#
|
211
|
-
# to at least one broadcast.
|
210
|
+
# True if the log level allows entries with severity +Logger::FATAL+ to be written
|
211
|
+
# to at least one broadcast. False otherwise.
|
212
212
|
def fatal?
|
213
213
|
@broadcasts.any? { |logger| logger.fatal? }
|
214
214
|
end
|
215
215
|
|
216
|
-
# Sets the log level to Logger::FATAL for the whole broadcast.
|
216
|
+
# Sets the log level to +Logger::FATAL+ for the whole broadcast.
|
217
217
|
def fatal!
|
218
218
|
dispatch { |logger| logger.fatal! }
|
219
219
|
end
|
@@ -57,7 +57,7 @@ module ActiveSupport
|
|
57
57
|
# cache.write("baz", 5)
|
58
58
|
# cache.increment("baz") # => 6
|
59
59
|
#
|
60
|
-
def increment(name, amount = 1, options
|
60
|
+
def increment(name, amount = 1, **options)
|
61
61
|
options = merged_options(options)
|
62
62
|
key = normalize_key(name, options)
|
63
63
|
|
@@ -77,7 +77,7 @@ module ActiveSupport
|
|
77
77
|
# cache.write("baz", 5)
|
78
78
|
# cache.decrement("baz") # => 4
|
79
79
|
#
|
80
|
-
def decrement(name, amount = 1, options
|
80
|
+
def decrement(name, amount = 1, **options)
|
81
81
|
options = merged_options(options)
|
82
82
|
key = normalize_key(name, options)
|
83
83
|
|
@@ -276,7 +276,7 @@ module ActiveSupport
|
|
276
276
|
|
277
277
|
def rescue_error_with(fallback)
|
278
278
|
yield
|
279
|
-
rescue Dalli::DalliError => error
|
279
|
+
rescue Dalli::DalliError, ConnectionPool::Error, ConnectionPool::TimeoutError => error
|
280
280
|
logger.error("DalliError (#{error}): #{error.message}") if logger
|
281
281
|
ActiveSupport.error_reporter&.report(
|
282
282
|
error,
|
@@ -146,9 +146,9 @@ module ActiveSupport
|
|
146
146
|
# cache.write("baz", 5)
|
147
147
|
# cache.increment("baz") # => 6
|
148
148
|
#
|
149
|
-
def increment(name, amount = 1, options
|
149
|
+
def increment(name, amount = 1, **options)
|
150
150
|
instrument(:increment, name, amount: amount) do
|
151
|
-
modify_value(name, amount, options)
|
151
|
+
modify_value(name, amount, **options)
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
@@ -163,9 +163,9 @@ module ActiveSupport
|
|
163
163
|
# cache.write("baz", 5)
|
164
164
|
# cache.decrement("baz") # => 4
|
165
165
|
#
|
166
|
-
def decrement(name, amount = 1, options
|
166
|
+
def decrement(name, amount = 1, **options)
|
167
167
|
instrument(:decrement, name, amount: amount) do
|
168
|
-
modify_value(name, -amount, options)
|
168
|
+
modify_value(name, -amount, **options)
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
@@ -238,7 +238,7 @@ module ActiveSupport
|
|
238
238
|
|
239
239
|
# Modifies the amount of an integer value that is stored in the cache.
|
240
240
|
# If the key is not found it is created and set to +amount+.
|
241
|
-
def modify_value(name, amount, options)
|
241
|
+
def modify_value(name, amount, **options)
|
242
242
|
options = merged_options(options)
|
243
243
|
key = normalize_key(name, options)
|
244
244
|
version = normalize_version(name, options)
|
@@ -25,10 +25,10 @@ module ActiveSupport
|
|
25
25
|
def cleanup(options = nil)
|
26
26
|
end
|
27
27
|
|
28
|
-
def increment(name, amount = 1, options
|
28
|
+
def increment(name, amount = 1, **options)
|
29
29
|
end
|
30
30
|
|
31
|
-
def decrement(name, amount = 1, options
|
31
|
+
def decrement(name, amount = 1, **options)
|
32
32
|
end
|
33
33
|
|
34
34
|
def delete_matched(matcher, options = nil)
|
@@ -483,7 +483,7 @@ module ActiveSupport
|
|
483
483
|
|
484
484
|
def failsafe(method, returning: nil)
|
485
485
|
yield
|
486
|
-
rescue ::Redis::BaseError => error
|
486
|
+
rescue ::Redis::BaseError, ConnectionPool::Error, ConnectionPool::TimeoutError => error
|
487
487
|
@error_handler&.call(method: method, exception: error, returning: returning)
|
488
488
|
returning
|
489
489
|
end
|
@@ -94,28 +94,54 @@ module ActiveSupport
|
|
94
94
|
super
|
95
95
|
end
|
96
96
|
|
97
|
-
def increment(name, amount = 1, options
|
97
|
+
def increment(name, amount = 1, **options) # :nodoc:
|
98
98
|
return super unless local_cache
|
99
99
|
value = bypass_local_cache { super }
|
100
|
-
|
101
|
-
write_cache_value(name, value, raw: true, **options)
|
102
|
-
else
|
103
|
-
write_cache_value(name, value, raw: true)
|
104
|
-
end
|
100
|
+
write_cache_value(name, value, raw: true, **options)
|
105
101
|
value
|
106
102
|
end
|
107
103
|
|
108
|
-
def decrement(name, amount = 1, options
|
104
|
+
def decrement(name, amount = 1, **options) # :nodoc:
|
109
105
|
return super unless local_cache
|
110
106
|
value = bypass_local_cache { super }
|
111
|
-
|
112
|
-
write_cache_value(name, value, raw: true, **options)
|
113
|
-
else
|
114
|
-
write_cache_value(name, value, raw: true)
|
115
|
-
end
|
107
|
+
write_cache_value(name, value, raw: true, **options)
|
116
108
|
value
|
117
109
|
end
|
118
110
|
|
111
|
+
def fetch_multi(*names, &block) # :nodoc:
|
112
|
+
return super if local_cache.nil? || names.empty?
|
113
|
+
|
114
|
+
options = names.extract_options!
|
115
|
+
options = merged_options(options)
|
116
|
+
|
117
|
+
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
118
|
+
|
119
|
+
local_entries = local_cache.read_multi_entries(keys_to_names.keys)
|
120
|
+
results = local_entries.each_with_object({}) do |(key, value), result|
|
121
|
+
# If we recorded a miss in the local cache, `#fetch_multi` will forward
|
122
|
+
# that key to the real store, and the entry will be replaced
|
123
|
+
# local_cache.delete_entry(key)
|
124
|
+
next if value.nil?
|
125
|
+
|
126
|
+
entry = deserialize_entry(value, **options)
|
127
|
+
|
128
|
+
normalized_key = keys_to_names[key]
|
129
|
+
if entry.nil?
|
130
|
+
result[normalized_key] = nil
|
131
|
+
elsif entry.expired? || entry.mismatched?(normalize_version(normalized_key, options))
|
132
|
+
local_cache.delete_entry(key)
|
133
|
+
else
|
134
|
+
result[normalized_key] = entry.value
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
if results.size < names.size
|
139
|
+
results.merge!(super(*(names - results.keys), options, &block))
|
140
|
+
end
|
141
|
+
|
142
|
+
results
|
143
|
+
end
|
144
|
+
|
119
145
|
private
|
120
146
|
def read_serialized_entry(key, raw: false, **options)
|
121
147
|
if cache = local_cache
|
@@ -137,17 +163,27 @@ module ActiveSupport
|
|
137
163
|
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
138
164
|
|
139
165
|
local_entries = local_cache.read_multi_entries(keys_to_names.keys)
|
140
|
-
|
141
|
-
local_entries.
|
142
|
-
|
166
|
+
|
167
|
+
results = local_entries.each_with_object({}) do |(key, value), result|
|
168
|
+
next if value.nil? # recorded cache miss
|
169
|
+
|
170
|
+
entry = deserialize_entry(value, **options)
|
171
|
+
|
172
|
+
normalized_key = keys_to_names[key]
|
173
|
+
if entry.nil?
|
174
|
+
result[normalized_key] = nil
|
175
|
+
elsif entry.expired? || entry.mismatched?(normalize_version(normalized_key, options))
|
176
|
+
local_cache.delete_entry(key)
|
177
|
+
else
|
178
|
+
result[normalized_key] = entry.value
|
179
|
+
end
|
143
180
|
end
|
144
|
-
missed_names = names - local_entries.keys
|
145
181
|
|
146
|
-
if
|
147
|
-
|
148
|
-
else
|
149
|
-
local_entries
|
182
|
+
if results.size < names.size
|
183
|
+
results.merge!(super(names - results.keys, **options))
|
150
184
|
end
|
185
|
+
|
186
|
+
results
|
151
187
|
end
|
152
188
|
|
153
189
|
def write_serialized_entry(key, payload, **)
|
data/lib/active_support/cache.rb
CHANGED
@@ -386,7 +386,7 @@ module ActiveSupport
|
|
386
386
|
# process can try to generate a new value after the extended time window
|
387
387
|
# has elapsed.
|
388
388
|
#
|
389
|
-
# # Set all values to expire after one
|
389
|
+
# # Set all values to expire after one second.
|
390
390
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1)
|
391
391
|
#
|
392
392
|
# cache.write("foo", "original value")
|
@@ -1035,8 +1035,7 @@ module ActiveSupport
|
|
1035
1035
|
# When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
|
1036
1036
|
# for a brief period while the entry is being recalculated.
|
1037
1037
|
entry.expires_at = Time.now.to_f + race_ttl
|
1038
|
-
options
|
1039
|
-
write_entry(key, entry, **options)
|
1038
|
+
write_entry(key, entry, **options, expires_in: race_ttl * 2)
|
1040
1039
|
else
|
1041
1040
|
delete_entry(key, **options)
|
1042
1041
|
end
|
@@ -498,9 +498,10 @@ module ActiveSupport
|
|
498
498
|
when Conditionals::Value
|
499
499
|
ProcCall.new(filter)
|
500
500
|
when ::Proc
|
501
|
-
|
501
|
+
case filter.arity
|
502
|
+
when 2
|
502
503
|
InstanceExec2.new(filter)
|
503
|
-
|
504
|
+
when 1, -2
|
504
505
|
InstanceExec1.new(filter)
|
505
506
|
else
|
506
507
|
InstanceExec0.new(filter)
|
@@ -203,7 +203,7 @@ module Enumerable
|
|
203
203
|
end
|
204
204
|
|
205
205
|
# Returns the sole item in the enumerable. If there are no items, or more
|
206
|
-
# than one item, raises
|
206
|
+
# than one item, raises Enumerable::SoleItemExpectedError.
|
207
207
|
#
|
208
208
|
# ["x"].sole # => "x"
|
209
209
|
# Set.new.sole # => Enumerable::SoleItemExpectedError: no item found
|
@@ -187,7 +187,7 @@ module ActiveSupport
|
|
187
187
|
super
|
188
188
|
return if name == :initialize
|
189
189
|
return unless public_method_defined?(name)
|
190
|
-
return if
|
190
|
+
return if singleton_class.method_defined?(name) || singleton_class.private_method_defined?(name)
|
191
191
|
Delegation.generate(singleton_class, [name], to: :instance, as: self, nilable: false)
|
192
192
|
end
|
193
193
|
end
|
@@ -207,6 +207,12 @@ module ActiveSupport
|
|
207
207
|
#
|
208
208
|
# Rails.error.report(error)
|
209
209
|
#
|
210
|
+
# The +error+ argument must be an instance of Exception.
|
211
|
+
#
|
212
|
+
# Rails.error.report(Exception.new("Something went wrong"))
|
213
|
+
#
|
214
|
+
# Otherwise you can use #unexpected to report an error which does accept a
|
215
|
+
# string argument.
|
210
216
|
def report(error, handled: true, severity: handled ? :warning : :error, context: {}, source: DEFAULT_SOURCE)
|
211
217
|
return if error.instance_variable_defined?(:@__rails_error_reported)
|
212
218
|
ensure_backtrace(error)
|
@@ -232,8 +238,11 @@ module ActiveSupport
|
|
232
238
|
end
|
233
239
|
end
|
234
240
|
|
235
|
-
|
236
|
-
error.
|
241
|
+
while error
|
242
|
+
unless error.frozen?
|
243
|
+
error.instance_variable_set(:@__rails_error_reported, true)
|
244
|
+
end
|
245
|
+
error = error.cause
|
237
246
|
end
|
238
247
|
|
239
248
|
nil
|
@@ -13,12 +13,30 @@ module ActiveSupport
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module JSON
|
16
|
-
# Dumps objects in JSON (JavaScript Object Notation).
|
17
|
-
# See http://www.json.org for more info.
|
18
|
-
#
|
19
|
-
# ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
|
20
|
-
# # => "{\"team\":\"rails\",\"players\":\"36\"}"
|
21
16
|
class << self
|
17
|
+
# Dumps objects in JSON (JavaScript Object Notation).
|
18
|
+
# See http://www.json.org for more info.
|
19
|
+
#
|
20
|
+
# ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
|
21
|
+
# # => "{\"team\":\"rails\",\"players\":\"36\"}"
|
22
|
+
#
|
23
|
+
# Generates JSON that is safe to include in JavaScript as it escapes
|
24
|
+
# U+2028 (Line Separator) and U+2029 (Paragraph Separator):
|
25
|
+
#
|
26
|
+
# ActiveSupport::JSON.encode({ key: "\u2028" })
|
27
|
+
# # => "{\"key\":\"\\u2028\"}"
|
28
|
+
#
|
29
|
+
# By default, it also generates JSON that is safe to include in HTML, as
|
30
|
+
# it escapes <tt><</tt>, <tt>></tt>, and <tt>&</tt>:
|
31
|
+
#
|
32
|
+
# ActiveSupport::JSON.encode({ key: "<>&" })
|
33
|
+
# # => "{\"key\":\"\\u003c\\u003e\\u0026\"}"
|
34
|
+
#
|
35
|
+
# This can be changed with the +escape_html_entities+ option, or the
|
36
|
+
# global escape_html_entities_in_json configuration option.
|
37
|
+
#
|
38
|
+
# ActiveSupport::JSON.encode({ key: "<>&" }, escape_html_entities: false)
|
39
|
+
# # => "{\"key\":\"<>&\"}"
|
22
40
|
def encode(value, options = nil)
|
23
41
|
Encoding.json_encoder.new(options).encode(value)
|
24
42
|
end
|
@@ -28,8 +28,8 @@ module ActiveSupport
|
|
28
28
|
# <tt>transitional = false</tt>.
|
29
29
|
|
30
30
|
##
|
31
|
-
# :method:
|
32
|
-
# :call-seq:
|
31
|
+
# :singleton-method: new
|
32
|
+
# :call-seq: new(&secret_generator)
|
33
33
|
#
|
34
34
|
# Initializes a new instance. +secret_generator+ must accept a salt and a
|
35
35
|
# +secret_length+ kwarg, and return a suitable secret (string) or secrets
|
@@ -154,6 +154,8 @@ module ActiveSupport
|
|
154
154
|
# not URL-safe. In other words, they can contain "+" and "/". If you want to
|
155
155
|
# generate URL-safe strings (in compliance with "Base 64 Encoding with URL
|
156
156
|
# and Filename Safe Alphabet" in RFC 4648), you can pass +true+.
|
157
|
+
# Note that MessageVerifier will always accept both URL-safe and URL-unsafe
|
158
|
+
# encoded messages, to allow a smooth transition between the two settings.
|
157
159
|
#
|
158
160
|
# [+:force_legacy_metadata_serializer+]
|
159
161
|
# Whether to use the legacy metadata serializer, which serializes the
|
@@ -318,6 +320,13 @@ module ActiveSupport
|
|
318
320
|
end
|
319
321
|
|
320
322
|
private
|
323
|
+
def decode(encoded, url_safe: @url_safe)
|
324
|
+
catch :invalid_message_format do
|
325
|
+
return super
|
326
|
+
end
|
327
|
+
super(encoded, url_safe: !url_safe)
|
328
|
+
end
|
329
|
+
|
321
330
|
def sign_encoded(encoded)
|
322
331
|
digest = generate_digest(encoded)
|
323
332
|
encoded << SEPARATOR << digest
|
@@ -28,8 +28,8 @@ module ActiveSupport
|
|
28
28
|
# <tt>transitional = false</tt>.
|
29
29
|
|
30
30
|
##
|
31
|
-
# :method:
|
32
|
-
# :call-seq:
|
31
|
+
# :singleton-method: new
|
32
|
+
# :call-seq: new(&secret_generator)
|
33
33
|
#
|
34
34
|
# Initializes a new instance. +secret_generator+ must accept a salt, and
|
35
35
|
# return a suitable secret (string). +secret_generator+ may also accept
|
@@ -59,7 +59,9 @@ module ActiveSupport
|
|
59
59
|
|
60
60
|
##
|
61
61
|
# :method: rotate
|
62
|
-
# :call-seq:
|
62
|
+
# :call-seq:
|
63
|
+
# rotate(**options)
|
64
|
+
# rotate(&block)
|
63
65
|
#
|
64
66
|
# Adds +options+ to the list of option sets. Messages will be signed using
|
65
67
|
# the first set in the list. When verifying, however, each set will be
|
@@ -55,7 +55,10 @@ module ActiveSupport # :nodoc:
|
|
55
55
|
# Creates a new Chars instance by wrapping _string_.
|
56
56
|
def initialize(string)
|
57
57
|
@wrapped_string = string
|
58
|
-
|
58
|
+
if string.encoding != Encoding::UTF_8
|
59
|
+
@wrapped_string = @wrapped_string.dup
|
60
|
+
@wrapped_string.force_encoding(Encoding::UTF_8)
|
61
|
+
end
|
59
62
|
end
|
60
63
|
|
61
64
|
# Forward all undefined methods to the wrapped string.
|
@@ -97,7 +97,9 @@ module ActiveSupport
|
|
97
97
|
end
|
98
98
|
|
99
99
|
initializer "active_support.to_time_preserves_timezone" do |app|
|
100
|
-
|
100
|
+
config.after_initialize do
|
101
|
+
ActiveSupport.to_time_preserves_timezone = app.config.active_support.to_time_preserves_timezone
|
102
|
+
end
|
101
103
|
end
|
102
104
|
|
103
105
|
# Sets the default week start
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activesupport
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.0.
|
4
|
+
version: 8.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-12 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: i18n
|
@@ -475,7 +474,6 @@ files:
|
|
475
474
|
- lib/active_support/testing/parallelize_executor.rb
|
476
475
|
- lib/active_support/testing/setup_and_teardown.rb
|
477
476
|
- lib/active_support/testing/stream.rb
|
478
|
-
- lib/active_support/testing/strict_warnings.rb
|
479
477
|
- lib/active_support/testing/tagged_logging.rb
|
480
478
|
- lib/active_support/testing/tests_without_assertions.rb
|
481
479
|
- lib/active_support/testing/time_helpers.rb
|
@@ -495,12 +493,11 @@ licenses:
|
|
495
493
|
- MIT
|
496
494
|
metadata:
|
497
495
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
498
|
-
changelog_uri: https://github.com/rails/rails/blob/v8.0.
|
499
|
-
documentation_uri: https://api.rubyonrails.org/v8.0.
|
496
|
+
changelog_uri: https://github.com/rails/rails/blob/v8.0.2/activesupport/CHANGELOG.md
|
497
|
+
documentation_uri: https://api.rubyonrails.org/v8.0.2/
|
500
498
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
501
|
-
source_code_uri: https://github.com/rails/rails/tree/v8.0.
|
499
|
+
source_code_uri: https://github.com/rails/rails/tree/v8.0.2/activesupport
|
502
500
|
rubygems_mfa_required: 'true'
|
503
|
-
post_install_message:
|
504
501
|
rdoc_options:
|
505
502
|
- "--encoding"
|
506
503
|
- UTF-8
|
@@ -517,8 +514,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
517
514
|
- !ruby/object:Gem::Version
|
518
515
|
version: '0'
|
519
516
|
requirements: []
|
520
|
-
rubygems_version: 3.
|
521
|
-
signing_key:
|
517
|
+
rubygems_version: 3.6.2
|
522
518
|
specification_version: 4
|
523
519
|
summary: A toolkit of support libraries and Ruby core extensions extracted from the
|
524
520
|
Rails framework.
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
$VERBOSE = true
|
4
|
-
Warning[:deprecated] = true
|
5
|
-
|
6
|
-
module ActiveSupport
|
7
|
-
module RaiseWarnings # :nodoc:
|
8
|
-
class WarningError < StandardError; end
|
9
|
-
|
10
|
-
PROJECT_ROOT = File.expand_path("../../../../", __dir__)
|
11
|
-
ALLOWED_WARNINGS = Regexp.union(
|
12
|
-
/circular require considered harmful.*delayed_job/, # Bug in delayed job.
|
13
|
-
|
14
|
-
# Expected non-verbose warning emitted by Rails.
|
15
|
-
/Ignoring .*\.yml because it has expired/,
|
16
|
-
/Failed to validate the schema cache because/,
|
17
|
-
|
18
|
-
# TODO: We need to decide what to do with this.
|
19
|
-
/Status code :unprocessable_entity is deprecated/,
|
20
|
-
)
|
21
|
-
|
22
|
-
SUPPRESSED_WARNINGS = Regexp.union(
|
23
|
-
# TODO: remove if https://github.com/mikel/mail/pull/1557 or similar fix
|
24
|
-
%r{/lib/mail/parsers/.*statement not reached},
|
25
|
-
%r{/lib/mail/parsers/.*assigned but unused variable - disp_type_s},
|
26
|
-
%r{/lib/mail/parsers/.*assigned but unused variable - testEof}
|
27
|
-
)
|
28
|
-
|
29
|
-
def warn(message, ...)
|
30
|
-
return if SUPPRESSED_WARNINGS.match?(message)
|
31
|
-
|
32
|
-
super
|
33
|
-
|
34
|
-
return unless message.include?(PROJECT_ROOT)
|
35
|
-
return if ALLOWED_WARNINGS.match?(message)
|
36
|
-
return unless ENV["RAILS_STRICT_WARNINGS"] || ENV["BUILDKITE"]
|
37
|
-
|
38
|
-
raise WarningError.new(message)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
Warning.singleton_class.prepend(ActiveSupport::RaiseWarnings)
|