activesupport 7.0.8 → 7.1.0.beta1
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 +736 -293
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +25 -5
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +128 -0
- data/lib/active_support/cache/file_store.rb +36 -9
- data/lib/active_support/cache/mem_cache_store.rb +84 -68
- data/lib/active_support/cache/memory_store.rb +76 -24
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +126 -131
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +20 -8
- data/lib/active_support/cache.rb +304 -246
- data/lib/active_support/callbacks.rb +38 -18
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +13 -10
- data/lib/active_support/core_ext/date/conversions.rb +1 -0
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -10
- data/lib/active_support/core_ext/enumerable.rb +3 -75
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/delegation.rb +40 -11
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +10 -2
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +3 -3
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- data/lib/active_support/core_ext/range/{overlaps.rb → overlap.rb} +5 -3
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/filters.rb +20 -14
- data/lib/active_support/core_ext/string/inflections.rb +16 -5
- data/lib/active_support/core_ext/string/output_safety.rb +38 -174
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +18 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +4 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/current_attributes.rb +15 -6
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/deprecation/behaviors.rb +53 -32
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +3 -5
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
- data/lib/active_support/deprecation/reporting.rb +35 -21
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +104 -132
- data/lib/active_support/duration/iso8601_serializer.rb +0 -2
- data/lib/active_support/duration.rb +2 -1
- data/lib/active_support/encrypted_configuration.rb +30 -9
- data/lib/active_support/encrypted_file.rb +8 -3
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +121 -35
- data/lib/active_support/execution_wrapper.rb +4 -4
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +10 -2
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +35 -17
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +22 -10
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +6 -4
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +78 -33
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_thread_safe_level.rb +9 -21
- data/lib/active_support/message_encryptor.rb +197 -53
- data/lib/active_support/message_encryptors.rb +140 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +212 -93
- data/lib/active_support/message_verifiers.rb +134 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +239 -81
- data/lib/active_support/notifications/instrumenter.rb +71 -14
- data/lib/active_support/notifications.rb +1 -1
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +14 -0
- data/lib/active_support/parameter_filter.rb +84 -69
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +33 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +3 -1
- data/lib/active_support/subscriber.rb +9 -27
- data/lib/active_support/syntax_error_proxy.rb +49 -0
- data/lib/active_support/tagged_logging.rb +60 -24
- data/lib/active_support/test_case.rb +153 -6
- data/lib/active_support/testing/assertions.rb +25 -9
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +25 -25
- data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
- data/lib/active_support/testing/isolation.rb +1 -1
- data/lib/active_support/testing/method_call_assertions.rb +21 -8
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +38 -0
- data/lib/active_support/testing/time_helpers.rb +32 -14
- data/lib/active_support/time_with_zone.rb +4 -14
- data/lib/active_support/values/time_zone.rb +9 -7
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -2
- data/lib/active_support.rb +13 -3
- metadata +102 -17
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/per_thread_registry.rb +0 -65
data/CHANGELOG.md
CHANGED
|
@@ -1,565 +1,1008 @@
|
|
|
1
|
-
## Rails 7.0.
|
|
1
|
+
## Rails 7.1.0.beta1 (September 13, 2023) ##
|
|
2
2
|
|
|
3
|
-
*
|
|
4
|
-
disable it are set.
|
|
3
|
+
* Add `drb`, `mutex_m` and `base64` that are bundled gem candidates for Ruby 3.4
|
|
5
4
|
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
* Fix CacheStore#write_multi when using a distributed Redis cache with a connection pool.
|
|
5
|
+
*Yasuo Honda*
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
* When using cache format version >= 7.1 or a custom serializer, expired and
|
|
8
|
+
version-mismatched cache entries can now be detected without deserializing
|
|
9
|
+
their values.
|
|
11
10
|
|
|
12
|
-
*Jonathan
|
|
11
|
+
*Jonathan Hefner*
|
|
13
12
|
|
|
13
|
+
* Make all cache stores return a boolean for `#delete`
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Previously the `RedisCacheStore#delete` would return `1` if the entry
|
|
16
|
+
exists and `0` otherwise. Now it returns true if the entry exists and false
|
|
17
|
+
otherwise, just like the other stores.
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
The `FileStore` would return `nil` if the entry doesn't exists and returns
|
|
20
|
+
`false` now as well.
|
|
18
21
|
|
|
22
|
+
*Petrik de Heus*
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
* Active Support cache stores now support replacing the default compressor via
|
|
25
|
+
a `:compressor` option. The specified compressor must respond to `deflate`
|
|
26
|
+
and `inflate`. For example:
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
```ruby
|
|
29
|
+
module MyCompressor
|
|
30
|
+
def self.deflate(string)
|
|
31
|
+
# compression logic...
|
|
32
|
+
end
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
def self.inflate(compressed)
|
|
35
|
+
# decompression logic...
|
|
36
|
+
end
|
|
37
|
+
end
|
|
25
38
|
|
|
39
|
+
config.cache_store = :redis_cache_store, { compressor: MyCompressor }
|
|
40
|
+
```
|
|
26
41
|
|
|
27
|
-
|
|
42
|
+
*Jonathan Hefner*
|
|
28
43
|
|
|
29
|
-
*
|
|
44
|
+
* Active Support cache stores now support a `:serializer` option. Similar to
|
|
45
|
+
the `:coder` option, serializers must respond to `dump` and `load`. However,
|
|
46
|
+
serializers are only responsible for serializing a cached value, whereas
|
|
47
|
+
coders are responsible for serializing the entire `ActiveSupport::Cache::Entry`
|
|
48
|
+
instance. Additionally, the output from serializers can be automatically
|
|
49
|
+
compressed, whereas coders are responsible for their own compression.
|
|
30
50
|
|
|
31
|
-
|
|
51
|
+
Specifying a serializer instead of a coder also enables performance
|
|
52
|
+
optimizations, including the bare string optimization introduced by cache
|
|
53
|
+
format version 7.1.
|
|
32
54
|
|
|
33
|
-
|
|
55
|
+
The `:serializer` and `:coder` options are mutually exclusive. Specifying
|
|
56
|
+
both will raise an `ArgumentError`.
|
|
34
57
|
|
|
35
|
-
*
|
|
58
|
+
*Jonathan Hefner*
|
|
36
59
|
|
|
37
60
|
* Fix `ActiveSupport::Inflector.humanize(nil)` raising ``NoMethodError: undefined method `end_with?' for nil:NilClass``.
|
|
38
61
|
|
|
39
62
|
*James Robinson*
|
|
40
63
|
|
|
41
|
-
*
|
|
64
|
+
* Don't show secrets for `ActiveSupport::KeyGenerator#inspect`.
|
|
65
|
+
|
|
66
|
+
Before:
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
ActiveSupport::KeyGenerator.new(secret).inspect
|
|
70
|
+
"#<ActiveSupport::KeyGenerator:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
|
|
71
|
+
```
|
|
42
72
|
|
|
43
|
-
|
|
73
|
+
After:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
ActiveSupport::KeyGenerator::Aes256Gcm(secret).inspect
|
|
77
|
+
"#<ActiveSupport::KeyGenerator:0x0000000104888038>"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
*Petrik de Heus*
|
|
44
81
|
|
|
45
82
|
* Improve error message when EventedFileUpdateChecker is used without a
|
|
46
83
|
compatible version of the Listen gem
|
|
47
84
|
|
|
48
85
|
*Hartley McGuire*
|
|
49
86
|
|
|
87
|
+
* Add `:report` behavior for Deprecation
|
|
50
88
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
* Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
|
|
54
|
-
methods
|
|
89
|
+
Setting `config.active_support.deprecation = :report` uses the error
|
|
90
|
+
reporter to report deprecation warnings to `ActiveSupport::ErrorReporter`.
|
|
55
91
|
|
|
56
|
-
|
|
92
|
+
Deprecations are reported as handled errors, with a severity of `:warning`.
|
|
57
93
|
|
|
58
|
-
|
|
94
|
+
Useful to report deprecations happening in production to your bug tracker.
|
|
59
95
|
|
|
60
|
-
|
|
96
|
+
*Étienne Barrié*
|
|
61
97
|
|
|
62
|
-
*
|
|
98
|
+
* Rename `Range#overlaps?` to `#overlap?` and add alias for backwards compatibility
|
|
63
99
|
|
|
64
|
-
*
|
|
100
|
+
*Christian Schmidt*
|
|
65
101
|
|
|
102
|
+
* Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
|
|
103
|
+
methods
|
|
66
104
|
|
|
67
|
-
|
|
105
|
+
*Hartley McGuire*
|
|
68
106
|
|
|
69
|
-
*
|
|
107
|
+
* Don't show secrets for `MessageEncryptor#inspect`.
|
|
70
108
|
|
|
109
|
+
Before:
|
|
71
110
|
|
|
72
|
-
|
|
111
|
+
```ruby
|
|
112
|
+
ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
|
|
113
|
+
"#<ActiveSupport::MessageEncryptor:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
|
|
114
|
+
```
|
|
73
115
|
|
|
74
|
-
|
|
116
|
+
After:
|
|
75
117
|
|
|
76
|
-
|
|
118
|
+
```ruby
|
|
119
|
+
ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
|
|
120
|
+
"#<ActiveSupport::MessageEncryptor:0x0000000104888038>"
|
|
121
|
+
```
|
|
77
122
|
|
|
123
|
+
*Petrik de Heus*
|
|
78
124
|
|
|
79
|
-
|
|
125
|
+
* Don't show contents for `EncryptedConfiguration#inspect`.
|
|
80
126
|
|
|
81
|
-
|
|
127
|
+
Before:
|
|
128
|
+
```ruby
|
|
129
|
+
Rails.application.credentials.inspect
|
|
130
|
+
"#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8 ... @config={:secret=>\"something secret\"} ... @key_file_contents=\"915e4ea054e011022398dc242\" ...>"
|
|
131
|
+
```
|
|
82
132
|
|
|
83
|
-
|
|
133
|
+
After:
|
|
134
|
+
```ruby
|
|
135
|
+
Rails.application.credentials.inspect
|
|
136
|
+
"#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8>"
|
|
137
|
+
```
|
|
84
138
|
|
|
139
|
+
*Petrik de Heus*
|
|
85
140
|
|
|
86
|
-
|
|
141
|
+
* `ERB::Util.html_escape_once` always returns an `html_safe` string.
|
|
87
142
|
|
|
88
|
-
|
|
143
|
+
This method previously maintained the `html_safe?` property of a string on the return
|
|
144
|
+
value. Because this string has been escaped, however, not marking it as `html_safe` causes
|
|
145
|
+
entities to be double-escaped.
|
|
89
146
|
|
|
147
|
+
As an example, take this view snippet:
|
|
90
148
|
|
|
91
|
-
|
|
149
|
+
```html
|
|
150
|
+
<p><%= html_escape_once("this & that & the other") %></p>
|
|
151
|
+
```
|
|
92
152
|
|
|
93
|
-
|
|
153
|
+
Before this change, that would be double-escaped and render as:
|
|
94
154
|
|
|
95
|
-
|
|
155
|
+
```html
|
|
156
|
+
<p>this &amp; that &amp; the other</p>
|
|
157
|
+
```
|
|
96
158
|
|
|
159
|
+
After this change, it renders correctly as:
|
|
97
160
|
|
|
98
|
-
|
|
161
|
+
```html
|
|
162
|
+
<p>this & that & the other</p>
|
|
163
|
+
```
|
|
99
164
|
|
|
100
|
-
|
|
165
|
+
Fixes #48256
|
|
101
166
|
|
|
102
|
-
|
|
103
|
-
process closed the read end, wrote to it, and then terminated (which
|
|
104
|
-
presumably closed the file descriptors on its end). The parent process
|
|
105
|
-
closed the write end, read from it, and returned, never closing the read
|
|
106
|
-
end.
|
|
167
|
+
*Mike Dalessio*
|
|
107
168
|
|
|
108
|
-
|
|
109
|
-
cause errors if the limit is reached.
|
|
169
|
+
* Deprecate `SafeBuffer#clone_empty`.
|
|
110
170
|
|
|
111
|
-
|
|
171
|
+
This method has not been used internally since Rails 4.2.0.
|
|
112
172
|
|
|
113
|
-
*
|
|
173
|
+
*Mike Dalessio*
|
|
114
174
|
|
|
115
|
-
|
|
175
|
+
* `MessageEncryptor`, `MessageVerifier`, and `config.active_support.message_serializer`
|
|
176
|
+
now accept `:message_pack` and `:message_pack_allow_marshal` as serializers.
|
|
177
|
+
These serializers require the [`msgpack` gem](https://rubygems.org/gems/msgpack)
|
|
178
|
+
(>= 1.7.0).
|
|
116
179
|
|
|
117
|
-
|
|
180
|
+
The Message Pack format can provide improved performance and smaller payload
|
|
181
|
+
sizes. It also supports round-tripping some Ruby types that are not supported
|
|
182
|
+
by JSON. For example:
|
|
118
183
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
184
|
+
```ruby
|
|
185
|
+
verifier = ActiveSupport::MessageVerifier.new("secret")
|
|
186
|
+
data = [{ a: 1 }, { b: 2 }.with_indifferent_access, 1.to_d, Time.at(0, 123)]
|
|
187
|
+
message = verifier.generate(data)
|
|
122
188
|
|
|
123
|
-
|
|
189
|
+
# BEFORE with config.active_support.message_serializer = :json
|
|
190
|
+
verifier.verified(message)
|
|
191
|
+
# => [{"a"=>1}, {"b"=>2}, "1.0", "1969-12-31T18:00:00.000-06:00"]
|
|
192
|
+
verifier.verified(message).map(&:class)
|
|
193
|
+
# => [Hash, Hash, String, String]
|
|
124
194
|
|
|
125
|
-
|
|
195
|
+
# AFTER with config.active_support.message_serializer = :message_pack
|
|
196
|
+
verifier.verified(message)
|
|
197
|
+
# => [{:a=>1}, {"b"=>2}, 0.1e1, 1969-12-31 18:00:00.000123 -0600]
|
|
198
|
+
verifier.verified(message).map(&:class)
|
|
199
|
+
# => [Hash, ActiveSupport::HashWithIndifferentAccess, BigDecimal, Time]
|
|
200
|
+
```
|
|
126
201
|
|
|
202
|
+
The `:message_pack` serializer can fall back to deserializing with
|
|
203
|
+
`ActiveSupport::JSON` when necessary, and the `:message_pack_allow_marshal`
|
|
204
|
+
serializer can fall back to deserializing with `Marshal` as well as
|
|
205
|
+
`ActiveSupport::JSON`. Additionally, the `:marshal`, `:json`, and
|
|
206
|
+
`:json_allow_marshal` serializers can now fall back to deserializing with
|
|
207
|
+
`ActiveSupport::MessagePack` when necessary. These behaviors ensure old
|
|
208
|
+
messages can still be read so that migration is easier.
|
|
127
209
|
|
|
128
|
-
|
|
210
|
+
*Jonathan Hefner*
|
|
129
211
|
|
|
130
|
-
*
|
|
212
|
+
* A new `7.1` cache format is available which includes an optimization for
|
|
213
|
+
bare string values such as view fragments.
|
|
131
214
|
|
|
215
|
+
The `7.1` cache format is used by default for new apps, and existing apps
|
|
216
|
+
can enable the format by setting `config.load_defaults 7.1` or by setting
|
|
217
|
+
`config.active_support.cache_format_version = 7.1` in `config/application.rb`
|
|
218
|
+
or a `config/environments/*.rb` file.
|
|
132
219
|
|
|
133
|
-
|
|
220
|
+
Cache entries written using the `6.1` or `7.0` cache formats can be read
|
|
221
|
+
when using the `7.1` format. To perform a rolling deploy of a Rails 7.1
|
|
222
|
+
upgrade, wherein servers that have not yet been upgraded must be able to
|
|
223
|
+
read caches from upgraded servers, leave the cache format unchanged on the
|
|
224
|
+
first deploy, then enable the `7.1` cache format on a subsequent deploy.
|
|
134
225
|
|
|
135
|
-
*
|
|
226
|
+
*Jonathan Hefner*
|
|
136
227
|
|
|
228
|
+
* Active Support cache stores can now use a preconfigured serializer based on
|
|
229
|
+
`ActiveSupport::MessagePack` via the `:serializer` option:
|
|
137
230
|
|
|
138
|
-
|
|
231
|
+
```ruby
|
|
232
|
+
config.cache_store = :redis_cache_store, { serializer: :message_pack }
|
|
233
|
+
```
|
|
139
234
|
|
|
140
|
-
|
|
235
|
+
The `:message_pack` serializer can reduce cache entry sizes and improve
|
|
236
|
+
performance, but requires the [`msgpack` gem](https://rubygems.org/gems/msgpack)
|
|
237
|
+
(>= 1.7.0).
|
|
141
238
|
|
|
142
|
-
|
|
143
|
-
|
|
239
|
+
The `:message_pack` serializer can read cache entries written by the default
|
|
240
|
+
serializer, and the default serializer can now read entries written by the
|
|
241
|
+
`:message_pack` serializer. These behaviors make it easy to migrate between
|
|
242
|
+
serializer without invalidating the entire cache.
|
|
144
243
|
|
|
145
|
-
|
|
244
|
+
*Jonathan Hefner*
|
|
146
245
|
|
|
147
|
-
|
|
246
|
+
* `Object#deep_dup` no longer duplicate named classes and modules.
|
|
148
247
|
|
|
149
|
-
|
|
248
|
+
Before:
|
|
150
249
|
|
|
250
|
+
```ruby
|
|
251
|
+
hash = { class: Object, module: Kernel }
|
|
252
|
+
hash.deep_dup # => {:class=>#<Class:0x00000001063ffc80>, :module=>#<Module:0x00000001063ffa00>}
|
|
253
|
+
```
|
|
151
254
|
|
|
152
|
-
|
|
255
|
+
After:
|
|
153
256
|
|
|
154
|
-
|
|
257
|
+
```ruby
|
|
258
|
+
hash = { class: Object, module: Kernel }
|
|
259
|
+
hash.deep_dup # => {:class=>Object, :module=>Kernel}
|
|
260
|
+
```
|
|
155
261
|
|
|
262
|
+
*Jean Boussier*
|
|
156
263
|
|
|
157
|
-
|
|
264
|
+
* Consistently raise an `ArgumentError` if the `ActiveSupport::Cache` key is blank.
|
|
158
265
|
|
|
159
|
-
*
|
|
266
|
+
*Joshua Young*
|
|
160
267
|
|
|
268
|
+
* Deprecate usage of the singleton `ActiveSupport::Deprecation`.
|
|
161
269
|
|
|
162
|
-
|
|
270
|
+
All usage of `ActiveSupport::Deprecation` as a singleton is deprecated, the most common one being
|
|
271
|
+
`ActiveSupport::Deprecation.warn`. Gem authors should now create their own deprecator (`ActiveSupport::Deprecation`
|
|
272
|
+
object), and use it to emit deprecation warnings.
|
|
163
273
|
|
|
164
|
-
|
|
274
|
+
Calling any of the following without specifying a deprecator argument is also deprecated:
|
|
275
|
+
* Module.deprecate
|
|
276
|
+
* deprecate_constant
|
|
277
|
+
* DeprecatedObjectProxy
|
|
278
|
+
* DeprecatedInstanceVariableProxy
|
|
279
|
+
* DeprecatedConstantProxy
|
|
280
|
+
* deprecation-related test assertions
|
|
165
281
|
|
|
166
|
-
|
|
282
|
+
Use of `ActiveSupport::Deprecation.silence` and configuration methods like `behavior=`, `disallowed_behavior=`,
|
|
283
|
+
`disallowed_warnings=` should now be aimed at the [application's deprecators](https://api.rubyonrails.org/classes/Rails/Application.html#method-i-deprecators).
|
|
167
284
|
|
|
168
|
-
|
|
285
|
+
```ruby
|
|
286
|
+
Rails.application.deprecators.silence do
|
|
287
|
+
# code that emits deprecation warnings
|
|
288
|
+
end
|
|
289
|
+
```
|
|
169
290
|
|
|
170
|
-
|
|
291
|
+
If your gem has a Railtie or Engine, it's encouraged to add your deprecator to the application's deprecators, that
|
|
292
|
+
way the deprecation related configuration options will apply to it as well, e.g.
|
|
293
|
+
`config.active_support.report_deprecations` set to `false` in the production environment will also disable your
|
|
294
|
+
deprecator.
|
|
171
295
|
|
|
296
|
+
```ruby
|
|
297
|
+
initializer "my_gem.deprecator" do |app|
|
|
298
|
+
app.deprecators[:my_gem] = MyGem.deprecator
|
|
299
|
+
end
|
|
300
|
+
```
|
|
172
301
|
|
|
173
|
-
|
|
302
|
+
*Étienne Barrié*
|
|
174
303
|
|
|
175
|
-
*
|
|
304
|
+
* Add `Object#with` to set and restore public attributes around a block
|
|
176
305
|
|
|
177
|
-
|
|
178
|
-
|
|
306
|
+
```ruby
|
|
307
|
+
client.timeout # => 5
|
|
308
|
+
client.with(timeout: 1) do
|
|
309
|
+
client.timeout # => 1
|
|
310
|
+
end
|
|
311
|
+
client.timeout # => 5
|
|
312
|
+
```
|
|
179
313
|
|
|
180
314
|
*Jean Boussier*
|
|
181
315
|
|
|
316
|
+
* Remove deprecated support to generate incorrect RFC 4122 UUIDs when providing a namespace ID that is not one of the
|
|
317
|
+
constants defined on `Digest::UUID`.
|
|
182
318
|
|
|
183
|
-
|
|
319
|
+
*Rafael Mendonça França*
|
|
320
|
+
|
|
321
|
+
* Deprecate `config.active_support.use_rfc4122_namespaced_uuids`.
|
|
322
|
+
|
|
323
|
+
*Rafael Mendonça França*
|
|
184
324
|
|
|
185
|
-
*
|
|
325
|
+
* Remove implicit conversion of objects into `String` by `ActiveSupport::SafeBuffer`.
|
|
186
326
|
|
|
187
|
-
|
|
188
|
-
ignored the sign of the `value` and accumulated incorrect part values. This
|
|
189
|
-
impacted `ActiveSupport::Duration#sum` (which is dependent on `parts`) but
|
|
190
|
-
not `ActiveSupport::Duration#eql?` (which is dependent on `value`).
|
|
327
|
+
*Rafael Mendonça França*
|
|
191
328
|
|
|
192
|
-
|
|
329
|
+
* Remove deprecated `active_support/core_ext/range/include_time_with_zone` file.
|
|
193
330
|
|
|
331
|
+
*Rafael Mendonça França*
|
|
194
332
|
|
|
195
|
-
|
|
333
|
+
* Deprecate `config.active_support.remove_deprecated_time_with_zone_name`.
|
|
196
334
|
|
|
197
|
-
*
|
|
335
|
+
*Rafael Mendonça França*
|
|
198
336
|
|
|
337
|
+
* Remove deprecated override of `ActiveSupport::TimeWithZone.name`.
|
|
199
338
|
|
|
200
|
-
|
|
339
|
+
*Rafael Mendonça França*
|
|
201
340
|
|
|
202
|
-
*
|
|
341
|
+
* Deprecate `config.active_support.disable_to_s_conversion`.
|
|
203
342
|
|
|
204
|
-
|
|
343
|
+
*Rafael Mendonça França*
|
|
205
344
|
|
|
206
|
-
*
|
|
345
|
+
* Remove deprecated option to passing a format to `#to_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
|
|
207
346
|
`BigDecimal`, `Float` and, `Integer`.
|
|
208
347
|
|
|
209
348
|
*Rafael Mendonça França*
|
|
210
349
|
|
|
211
|
-
*
|
|
350
|
+
* Remove deprecated `ActiveSupport::PerThreadRegistry`.
|
|
212
351
|
|
|
213
|
-
*
|
|
352
|
+
*Rafael Mendonça França*
|
|
214
353
|
|
|
215
|
-
*
|
|
354
|
+
* Remove deprecated override of `Enumerable#sum`.
|
|
216
355
|
|
|
217
|
-
|
|
218
|
-
Pathname.new("file").existence&.read
|
|
219
|
-
```
|
|
356
|
+
*Rafael Mendonça França*
|
|
220
357
|
|
|
221
|
-
|
|
358
|
+
* Deprecated initializing a `ActiveSupport::Cache::MemCacheStore` with an instance of `Dalli::Client`.
|
|
222
359
|
|
|
223
|
-
|
|
360
|
+
Deprecate the undocumented option of providing an already-initialized instance of `Dalli::Client` to `ActiveSupport::Cache::MemCacheStore`. Such clients could be configured with unrecognized options, which could lead to unexpected behavior. Instead, provide addresses as documented.
|
|
224
361
|
|
|
225
|
-
*
|
|
362
|
+
*aledustet*
|
|
226
363
|
|
|
227
|
-
*
|
|
228
|
-
a date time range is deprecated.
|
|
364
|
+
* Stub `Time.new()` in `TimeHelpers#travel_to`
|
|
229
365
|
|
|
230
|
-
|
|
366
|
+
```ruby
|
|
367
|
+
travel_to Time.new(2004, 11, 24) do
|
|
368
|
+
# Inside the `travel_to` block `Time.new` is stubbed
|
|
369
|
+
assert_equal Time.new.year, 2004
|
|
370
|
+
end
|
|
371
|
+
```
|
|
231
372
|
|
|
232
|
-
*
|
|
373
|
+
*fatkodima*
|
|
233
374
|
|
|
234
|
-
|
|
375
|
+
* Raise `ActiveSupport::MessageEncryptor::InvalidMessage` from
|
|
376
|
+
`ActiveSupport::MessageEncryptor#decrypt_and_verify` regardless of cipher.
|
|
377
|
+
Previously, when a `MessageEncryptor` was using a non-AEAD cipher such as
|
|
378
|
+
AES-256-CBC, a corrupt or tampered message would raise
|
|
379
|
+
`ActiveSupport::MessageVerifier::InvalidSignature`. Now, all ciphers raise
|
|
380
|
+
the same error:
|
|
235
381
|
|
|
236
|
-
|
|
382
|
+
```ruby
|
|
383
|
+
encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-gcm")
|
|
384
|
+
message = encryptor.encrypt_and_sign("message")
|
|
385
|
+
encryptor.decrypt_and_verify(message.next)
|
|
386
|
+
# => raises ActiveSupport::MessageEncryptor::InvalidMessage
|
|
237
387
|
|
|
238
|
-
|
|
388
|
+
encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-cbc")
|
|
389
|
+
message = encryptor.encrypt_and_sign("message")
|
|
390
|
+
encryptor.decrypt_and_verify(message.next)
|
|
391
|
+
# BEFORE:
|
|
392
|
+
# => raises ActiveSupport::MessageVerifier::InvalidSignature
|
|
393
|
+
# AFTER:
|
|
394
|
+
# => raises ActiveSupport::MessageEncryptor::InvalidMessage
|
|
395
|
+
```
|
|
239
396
|
|
|
240
|
-
*
|
|
241
|
-
`ActiveSupport::OptionMerger` instance.
|
|
397
|
+
*Jonathan Hefner*
|
|
242
398
|
|
|
243
|
-
|
|
399
|
+
* Support `nil` original values when using `ActiveSupport::MessageVerifier#verify`.
|
|
400
|
+
Previously, `MessageVerifier#verify` did not work with `nil` original
|
|
401
|
+
values, though both `MessageVerifier#verified` and
|
|
402
|
+
`MessageEncryptor#decrypt_and_verify` do:
|
|
244
403
|
|
|
245
|
-
|
|
404
|
+
```ruby
|
|
405
|
+
encryptor = ActiveSupport::MessageEncryptor.new(secret)
|
|
406
|
+
message = encryptor.encrypt_and_sign(nil)
|
|
246
407
|
|
|
247
|
-
|
|
248
|
-
|
|
408
|
+
encryptor.decrypt_and_verify(message)
|
|
409
|
+
# => nil
|
|
249
410
|
|
|
250
|
-
|
|
411
|
+
verifier = ActiveSupport::MessageVerifier.new(secret)
|
|
412
|
+
message = verifier.generate(nil)
|
|
251
413
|
|
|
252
|
-
|
|
414
|
+
verifier.verified(message)
|
|
415
|
+
# => nil
|
|
253
416
|
|
|
254
|
-
|
|
417
|
+
verifier.verify(message)
|
|
418
|
+
# BEFORE:
|
|
419
|
+
# => raises ActiveSupport::MessageVerifier::InvalidSignature
|
|
420
|
+
# AFTER:
|
|
421
|
+
# => nil
|
|
422
|
+
```
|
|
255
423
|
|
|
256
|
-
*
|
|
424
|
+
*Jonathan Hefner*
|
|
257
425
|
|
|
258
|
-
|
|
426
|
+
* Maintain `html_safe?` on html_safe strings when sliced with `slice`, `slice!`, or `chr` method.
|
|
259
427
|
|
|
260
|
-
|
|
428
|
+
Previously, `html_safe?` was only maintained when the html_safe strings were sliced
|
|
429
|
+
with `[]` method. Now, `slice`, `slice!`, and `chr` methods will maintain `html_safe?` like `[]` method.
|
|
261
430
|
|
|
262
|
-
|
|
263
|
-
|
|
431
|
+
```ruby
|
|
432
|
+
string = "<div>test</div>".html_safe
|
|
433
|
+
string.slice(0, 1).html_safe? # => true
|
|
434
|
+
string.slice!(0, 1).html_safe? # => true
|
|
435
|
+
# maintain html_safe? after the slice!
|
|
436
|
+
string.html_safe? # => true
|
|
437
|
+
string.chr # => true
|
|
438
|
+
```
|
|
264
439
|
|
|
265
|
-
*
|
|
440
|
+
*Michael Go*
|
|
266
441
|
|
|
267
|
-
*
|
|
442
|
+
* Add `Object#in?` support for open ranges.
|
|
268
443
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
444
|
+
```ruby
|
|
445
|
+
assert Date.today.in?(..Date.tomorrow)
|
|
446
|
+
assert_not Date.today.in?(Date.tomorrow..)
|
|
447
|
+
```
|
|
272
448
|
|
|
273
|
-
|
|
274
|
-
deprecation warning every time a value that is different than one of
|
|
275
|
-
the constants defined on the `Digest::UUID` extension is used as the
|
|
276
|
-
namespace ID.
|
|
449
|
+
*Ignacio Galindo*
|
|
277
450
|
|
|
278
|
-
|
|
451
|
+
* `config.i18n.raise_on_missing_translations = true` now raises on any missing translation.
|
|
279
452
|
|
|
280
|
-
|
|
281
|
-
|
|
453
|
+
Previously it would only raise when called in a view or controller. Now it will raise
|
|
454
|
+
anytime `I18n.t` is provided an unrecognised key.
|
|
282
455
|
|
|
283
|
-
|
|
456
|
+
If you do not want this behaviour, you can customise the i18n exception handler. See the
|
|
457
|
+
upgrading guide or i18n guide for more information.
|
|
284
458
|
|
|
459
|
+
*Alex Ghiculescu*
|
|
285
460
|
|
|
286
|
-
|
|
461
|
+
* `ActiveSupport::CurrentAttributes` now raises if a restricted attribute name is used.
|
|
287
462
|
|
|
288
|
-
|
|
463
|
+
Attributes such as `set` and `reset` cannot be used as they clash with the
|
|
464
|
+
`CurrentAttributes` public API.
|
|
289
465
|
|
|
466
|
+
*Alex Ghiculescu*
|
|
290
467
|
|
|
291
|
-
|
|
468
|
+
* `HashWithIndifferentAccess#transform_keys` now takes a Hash argument, just
|
|
469
|
+
as Ruby's `Hash#transform_keys` does.
|
|
292
470
|
|
|
293
|
-
*
|
|
471
|
+
*Akira Matsuda*
|
|
294
472
|
|
|
295
|
-
|
|
473
|
+
* `delegate` now defines method with proper arity when delegating to a Class.
|
|
474
|
+
With this change, it defines faster method (3.5x faster with no argument).
|
|
475
|
+
However, in order to gain this benefit, the delegation target method has to
|
|
476
|
+
be defined before declaring the delegation.
|
|
296
477
|
|
|
297
|
-
|
|
478
|
+
```ruby
|
|
479
|
+
# This defines 3.5 times faster method than before
|
|
480
|
+
class C
|
|
481
|
+
def self.x() end
|
|
482
|
+
delegate :x, to: :class
|
|
483
|
+
end
|
|
298
484
|
|
|
299
|
-
|
|
485
|
+
class C
|
|
486
|
+
# This works but silently falls back to old behavior because
|
|
487
|
+
# `delegate` cannot find the definition of `x`
|
|
488
|
+
delegate :x, to: :class
|
|
489
|
+
def self.x() end
|
|
490
|
+
end
|
|
491
|
+
```
|
|
300
492
|
|
|
301
|
-
*
|
|
493
|
+
*Akira Matsuda*
|
|
302
494
|
|
|
303
|
-
|
|
495
|
+
* `assert_difference` message now includes what changed.
|
|
304
496
|
|
|
305
|
-
|
|
497
|
+
This makes it easier to debug non-obvious failures.
|
|
306
498
|
|
|
307
|
-
|
|
499
|
+
Before:
|
|
308
500
|
|
|
309
|
-
|
|
501
|
+
```
|
|
502
|
+
"User.count" didn't change by 32.
|
|
503
|
+
Expected: 1611
|
|
504
|
+
Actual: 1579
|
|
505
|
+
```
|
|
310
506
|
|
|
311
|
-
|
|
312
|
-
the error handler would be rescued and logged only. Removed the `rescue` clause from `handle_exception`
|
|
313
|
-
to allow these to be thrown.
|
|
507
|
+
After:
|
|
314
508
|
|
|
315
|
-
|
|
509
|
+
```
|
|
510
|
+
"User.count" didn't change by 32, but by 0.
|
|
511
|
+
Expected: 1611
|
|
512
|
+
Actual: 1579
|
|
513
|
+
```
|
|
316
514
|
|
|
317
|
-
*
|
|
515
|
+
*Alex Ghiculescu*
|
|
318
516
|
|
|
319
|
-
|
|
320
|
-
still be done on each call to `ActiveSupport::Deprecation.warn`. In very hot paths, this could
|
|
321
|
-
cause performance issues.
|
|
517
|
+
* Add ability to match exception messages to `assert_raises` assertion
|
|
322
518
|
|
|
323
|
-
|
|
519
|
+
Instead of this
|
|
520
|
+
```ruby
|
|
521
|
+
error = assert_raises(ArgumentError) do
|
|
522
|
+
perform_service(param: 'exception')
|
|
523
|
+
end
|
|
524
|
+
assert_match(/incorrect param/i, error.message)
|
|
525
|
+
```
|
|
324
526
|
|
|
527
|
+
you can now write this
|
|
325
528
|
```ruby
|
|
326
|
-
|
|
529
|
+
assert_raises(ArgumentError, match: /incorrect param/i) do
|
|
530
|
+
perform_service(param: 'exception')
|
|
531
|
+
end
|
|
327
532
|
```
|
|
328
533
|
|
|
329
|
-
|
|
534
|
+
*fatkodima*
|
|
535
|
+
|
|
536
|
+
* Add `Rails.env.local?` shorthand for `Rails.env.development? || Rails.env.test?`.
|
|
537
|
+
|
|
538
|
+
*DHH*
|
|
539
|
+
|
|
540
|
+
* `ActiveSupport::Testing::TimeHelpers` now accepts named `with_usec` argument
|
|
541
|
+
to `freeze_time`, `travel`, and `travel_to` methods. Passing true prevents
|
|
542
|
+
truncating the destination time with `change(usec: 0)`.
|
|
543
|
+
|
|
544
|
+
*KevSlashNull*, and *serprex*
|
|
545
|
+
|
|
546
|
+
* `ActiveSupport::CurrentAttributes.resets` now accepts a method name
|
|
547
|
+
|
|
548
|
+
The block API is still the recommended approach, but now both APIs are supported:
|
|
330
549
|
|
|
331
550
|
```ruby
|
|
332
|
-
|
|
333
|
-
|
|
551
|
+
class Current < ActiveSupport::CurrentAttributes
|
|
552
|
+
resets { Time.zone = nil }
|
|
553
|
+
resets :clear_time_zone
|
|
554
|
+
end
|
|
334
555
|
```
|
|
335
556
|
|
|
336
|
-
but will take a more optimised code path.
|
|
337
|
-
|
|
338
557
|
*Alex Ghiculescu*
|
|
339
558
|
|
|
340
|
-
*
|
|
341
|
-
of them.
|
|
559
|
+
* Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
|
|
342
560
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
561
|
+
Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
|
|
562
|
+
process closed the read end, wrote to it, and then terminated (which
|
|
563
|
+
presumably closed the file descriptors on its end). The parent process
|
|
564
|
+
closed the write end, read from it, and returned, never closing the read
|
|
565
|
+
end.
|
|
346
566
|
|
|
347
|
-
This
|
|
348
|
-
|
|
567
|
+
This resulted in an accumulation of open file descriptors, which could
|
|
568
|
+
cause errors if the limit is reached.
|
|
569
|
+
|
|
570
|
+
*Sam Bostock*
|
|
571
|
+
|
|
572
|
+
* Fix `Time#change` and `Time#advance` for times around the end of Daylight
|
|
573
|
+
Saving Time.
|
|
574
|
+
|
|
575
|
+
Previously, when `Time#change` or `Time#advance` constructed a time inside
|
|
576
|
+
the final stretch of Daylight Saving Time (DST), the non-DST offset would
|
|
577
|
+
always be chosen for local times:
|
|
349
578
|
|
|
350
579
|
```ruby
|
|
351
|
-
|
|
580
|
+
# DST ended just before 2021-11-07 2:00:00 AM in US/Eastern.
|
|
581
|
+
ENV["TZ"] = "US/Eastern"
|
|
582
|
+
|
|
583
|
+
time = Time.local(2021, 11, 07, 00, 59, 59) + 1
|
|
584
|
+
# => 2021-11-07 01:00:00 -0400
|
|
585
|
+
time.change(day: 07)
|
|
586
|
+
# => 2021-11-07 01:00:00 -0500
|
|
587
|
+
time.advance(seconds: 0)
|
|
588
|
+
# => 2021-11-07 01:00:00 -0500
|
|
589
|
+
|
|
590
|
+
time = Time.local(2021, 11, 06, 01, 00, 00)
|
|
591
|
+
# => 2021-11-06 01:00:00 -0400
|
|
592
|
+
time.change(day: 07)
|
|
593
|
+
# => 2021-11-07 01:00:00 -0500
|
|
594
|
+
time.advance(days: 1)
|
|
595
|
+
# => 2021-11-07 01:00:00 -0500
|
|
352
596
|
```
|
|
353
597
|
|
|
354
|
-
|
|
598
|
+
And the DST offset would always be chosen for times with a `TimeZone`
|
|
599
|
+
object:
|
|
355
600
|
|
|
356
601
|
```ruby
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
602
|
+
Time.zone = "US/Eastern"
|
|
603
|
+
|
|
604
|
+
time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
|
|
605
|
+
# => 2021-11-07 01:00:00 -0500
|
|
606
|
+
time.change(day: 07)
|
|
607
|
+
# => 2021-11-07 01:00:00 -0400
|
|
608
|
+
time.advance(seconds: 0)
|
|
609
|
+
# => 2021-11-07 01:00:00 -0400
|
|
610
|
+
|
|
611
|
+
time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
|
|
612
|
+
# => 2021-11-08 01:00:00 -0500
|
|
613
|
+
time.change(day: 07)
|
|
614
|
+
# => 2021-11-07 01:00:00 -0400
|
|
615
|
+
time.advance(days: -1)
|
|
616
|
+
# => 2021-11-07 01:00:00 -0400
|
|
360
617
|
```
|
|
361
618
|
|
|
362
|
-
|
|
619
|
+
Now, `Time#change` and `Time#advance` will choose the offset that matches
|
|
620
|
+
the original time's offset when possible:
|
|
363
621
|
|
|
364
|
-
|
|
622
|
+
```ruby
|
|
623
|
+
ENV["TZ"] = "US/Eastern"
|
|
624
|
+
|
|
625
|
+
time = Time.local(2021, 11, 07, 00, 59, 59) + 1
|
|
626
|
+
# => 2021-11-07 01:00:00 -0400
|
|
627
|
+
time.change(day: 07)
|
|
628
|
+
# => 2021-11-07 01:00:00 -0400
|
|
629
|
+
time.advance(seconds: 0)
|
|
630
|
+
# => 2021-11-07 01:00:00 -0400
|
|
631
|
+
|
|
632
|
+
time = Time.local(2021, 11, 06, 01, 00, 00)
|
|
633
|
+
# => 2021-11-06 01:00:00 -0400
|
|
634
|
+
time.change(day: 07)
|
|
635
|
+
# => 2021-11-07 01:00:00 -0400
|
|
636
|
+
time.advance(days: 1)
|
|
637
|
+
# => 2021-11-07 01:00:00 -0400
|
|
638
|
+
|
|
639
|
+
Time.zone = "US/Eastern"
|
|
640
|
+
|
|
641
|
+
time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
|
|
642
|
+
# => 2021-11-07 01:00:00 -0500
|
|
643
|
+
time.change(day: 07)
|
|
644
|
+
# => 2021-11-07 01:00:00 -0500
|
|
645
|
+
time.advance(seconds: 0)
|
|
646
|
+
# => 2021-11-07 01:00:00 -0500
|
|
647
|
+
|
|
648
|
+
time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
|
|
649
|
+
# => 2021-11-08 01:00:00 -0500
|
|
650
|
+
time.change(day: 07)
|
|
651
|
+
# => 2021-11-07 01:00:00 -0500
|
|
652
|
+
time.advance(days: -1)
|
|
653
|
+
# => 2021-11-07 01:00:00 -0500
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
*Kevin Hall*, *Takayoshi Nishida*, and *Jonathan Hefner*
|
|
657
|
+
|
|
658
|
+
* Fix MemoryStore to preserve entries TTL when incrementing or decrementing
|
|
365
659
|
|
|
366
|
-
|
|
660
|
+
This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.
|
|
367
661
|
|
|
368
|
-
*
|
|
369
|
-
|
|
370
|
-
|
|
662
|
+
*Jean Boussier*
|
|
663
|
+
|
|
664
|
+
* `Rails.error.handle` and `Rails.error.record` filter now by multiple error classes.
|
|
371
665
|
|
|
372
666
|
```ruby
|
|
373
|
-
|
|
374
|
-
|
|
667
|
+
Rails.error.handle(IOError, ArgumentError) do
|
|
668
|
+
1 + '1' # raises TypeError
|
|
669
|
+
end
|
|
670
|
+
1 + 1 # TypeErrors are not IOErrors or ArgumentError, so this will *not* be handled
|
|
375
671
|
```
|
|
376
672
|
|
|
377
|
-
*
|
|
673
|
+
*Martin Spickermann*
|
|
378
674
|
|
|
379
|
-
* `
|
|
380
|
-
return a `Time` with the timezone argument provided, if the caller was
|
|
381
|
-
initialized with a timezone argument.
|
|
675
|
+
* `Class#subclasses` and `Class#descendants` now automatically filter reloaded classes.
|
|
382
676
|
|
|
383
|
-
|
|
677
|
+
Previously they could return old implementations of reloadable classes that have been
|
|
678
|
+
dereferenced but not yet garbage collected.
|
|
384
679
|
|
|
385
|
-
|
|
680
|
+
They now automatically filter such classes like `DescendantTracker#subclasses` and
|
|
681
|
+
`DescendantTracker#descendants`.
|
|
386
682
|
|
|
387
|
-
*
|
|
683
|
+
*Jean Boussier*
|
|
684
|
+
|
|
685
|
+
* `Rails.error.report` now marks errors as reported to avoid reporting them twice.
|
|
388
686
|
|
|
389
|
-
|
|
687
|
+
In some cases, users might want to report errors explicitly with some extra context
|
|
688
|
+
before letting it bubble up.
|
|
390
689
|
|
|
391
|
-
|
|
392
|
-
`RAILS_MASTER_KEY` environment variable is blank (e.g. `""`).
|
|
690
|
+
This also allows to safely catch and report errors outside of the execution context.
|
|
393
691
|
|
|
394
|
-
*
|
|
692
|
+
*Jean Boussier*
|
|
395
693
|
|
|
396
|
-
*
|
|
694
|
+
* Add `assert_error_reported` and `assert_no_error_reported`
|
|
397
695
|
|
|
398
|
-
|
|
696
|
+
Allows to easily asserts an error happened but was handled
|
|
399
697
|
|
|
400
698
|
```ruby
|
|
401
|
-
|
|
402
|
-
|
|
699
|
+
report = assert_error_reported(IOError) do
|
|
700
|
+
# ...
|
|
403
701
|
end
|
|
702
|
+
assert_equal "Oops", report.error.message
|
|
703
|
+
assert_equal "admin", report.context[:section]
|
|
704
|
+
assert_equal :warning, report.severity
|
|
705
|
+
assert_predicate report, :handled?
|
|
404
706
|
```
|
|
405
707
|
|
|
406
|
-
*
|
|
708
|
+
*Jean Boussier*
|
|
407
709
|
|
|
408
|
-
*
|
|
710
|
+
* `ActiveSupport::Deprecation` behavior callbacks can now receive the
|
|
711
|
+
deprecator instance as an argument. This makes it easier for such callbacks
|
|
712
|
+
to change their behavior based on the deprecator's state. For example,
|
|
713
|
+
based on the deprecator's `debug` flag.
|
|
409
714
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
circumstances `ActiveSupport::SafeBuffer` was incorrectly calling the
|
|
413
|
-
explicit conversion method (`#to_s`) on them. This behavior is now
|
|
414
|
-
deprecated.
|
|
715
|
+
3-arity and splat-args callbacks such as the following will now be passed
|
|
716
|
+
the deprecator instance as their third argument:
|
|
415
717
|
|
|
416
|
-
*
|
|
718
|
+
* `->(message, callstack, deprecator) { ... }`
|
|
719
|
+
* `->(*args) { ... }`
|
|
720
|
+
* `->(message, *other_args) { ... }`
|
|
721
|
+
|
|
722
|
+
2-arity and 4-arity callbacks such as the following will continue to behave
|
|
723
|
+
the same as before:
|
|
724
|
+
|
|
725
|
+
* `->(message, callstack) { ... }`
|
|
726
|
+
* `->(message, callstack, deprecation_horizon, gem_name) { ... }`
|
|
727
|
+
* `->(message, callstack, *deprecation_details) { ... }`
|
|
417
728
|
|
|
418
|
-
*
|
|
729
|
+
*Jonathan Hefner*
|
|
419
730
|
|
|
420
|
-
|
|
731
|
+
* `ActiveSupport::Deprecation#disallowed_warnings` now affects the instance on
|
|
732
|
+
which it is configured.
|
|
421
733
|
|
|
422
|
-
|
|
734
|
+
This means that individual `ActiveSupport::Deprecation` instances can be
|
|
735
|
+
configured with their own disallowed warnings, and the global
|
|
736
|
+
`ActiveSupport::Deprecation.disallowed_warnings` now only affects the global
|
|
737
|
+
`ActiveSupport::Deprecation.warn`.
|
|
423
738
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
739
|
+
**Before**
|
|
740
|
+
|
|
741
|
+
```ruby
|
|
742
|
+
ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
|
|
743
|
+
deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
|
|
744
|
+
deprecator.disallowed_warnings = ["bar"]
|
|
745
|
+
|
|
746
|
+
ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
|
|
747
|
+
ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
|
|
748
|
+
deprecator.warn("foo") # => raise ActiveSupport::DeprecationException
|
|
749
|
+
deprecator.warn("bar") # => print "DEPRECATION WARNING: bar"
|
|
428
750
|
```
|
|
429
751
|
|
|
430
|
-
|
|
431
|
-
`Rails.application.credentials.aws[:access_key_id]`.
|
|
752
|
+
**After**
|
|
432
753
|
|
|
433
|
-
|
|
754
|
+
```ruby
|
|
755
|
+
ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
|
|
756
|
+
deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
|
|
757
|
+
deprecator.disallowed_warnings = ["bar"]
|
|
758
|
+
|
|
759
|
+
ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
|
|
760
|
+
ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
|
|
761
|
+
deprecator.warn("foo") # => print "DEPRECATION WARNING: foo"
|
|
762
|
+
deprecator.warn("bar") # => raise ActiveSupport::DeprecationException
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
Note that global `ActiveSupport::Deprecation` methods such as `ActiveSupport::Deprecation.warn`
|
|
766
|
+
and `ActiveSupport::Deprecation.disallowed_warnings` have been deprecated.
|
|
767
|
+
|
|
768
|
+
*Jonathan Hefner*
|
|
769
|
+
|
|
770
|
+
* Add italic and underline support to `ActiveSupport::LogSubscriber#color`
|
|
771
|
+
|
|
772
|
+
Previously, only bold text was supported via a positional argument.
|
|
773
|
+
This allows for bold, italic, and underline options to be specified
|
|
774
|
+
for colored logs.
|
|
775
|
+
|
|
776
|
+
```ruby
|
|
777
|
+
info color("Hello world!", :red, bold: true, underline: true)
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
*Gannon McGibbon*
|
|
781
|
+
|
|
782
|
+
* Add `String#downcase_first` method.
|
|
783
|
+
|
|
784
|
+
This method is the corollary of `String#upcase_first`.
|
|
785
|
+
|
|
786
|
+
*Mark Schneider*
|
|
787
|
+
|
|
788
|
+
* `thread_mattr_accessor` will call `.dup.freeze` on non-frozen default values.
|
|
789
|
+
|
|
790
|
+
This provides a basic level of protection against different threads trying
|
|
791
|
+
to mutate a shared default object.
|
|
792
|
+
|
|
793
|
+
*Jonathan Hefner*
|
|
794
|
+
|
|
795
|
+
* Add `raise_on_invalid_cache_expiration_time` config to `ActiveSupport::Cache::Store`
|
|
796
|
+
|
|
797
|
+
Specifies if an `ArgumentError` should be raised if `Rails.cache` `fetch` or
|
|
798
|
+
`write` are given an invalid `expires_at` or `expires_in` time.
|
|
799
|
+
|
|
800
|
+
Options are `true`, and `false`. If `false`, the exception will be reported
|
|
801
|
+
as `handled` and logged instead. Defaults to `true` if `config.load_defaults >= 7.1`.
|
|
802
|
+
|
|
803
|
+
*Trevor Turk*
|
|
804
|
+
|
|
805
|
+
* `ActiveSupport::Cache:Store#fetch` now passes an options accessor to the block.
|
|
806
|
+
|
|
807
|
+
It makes possible to override cache options:
|
|
808
|
+
|
|
809
|
+
Rails.cache.fetch("3rd-party-token") do |name, options|
|
|
810
|
+
token = fetch_token_from_remote
|
|
811
|
+
# set cache's TTL to match token's TTL
|
|
812
|
+
options.expires_in = token.expires_in
|
|
813
|
+
token
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
*Andrii Gladkyi*, *Jean Boussier*
|
|
817
|
+
|
|
818
|
+
* `default` option of `thread_mattr_accessor` now applies through inheritance and
|
|
819
|
+
also across new threads.
|
|
820
|
+
|
|
821
|
+
Previously, the `default` value provided was set only at the moment of defining
|
|
822
|
+
the attribute writer, which would cause the attribute to be uninitialized in
|
|
823
|
+
descendants and in other threads.
|
|
434
824
|
|
|
435
|
-
|
|
825
|
+
Fixes #43312.
|
|
436
826
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
upgrade without invalidating the cache. However Rails 6.1 can't read the
|
|
441
|
-
new format, so all readers must be upgraded before the new format is enabled.
|
|
827
|
+
*Thierry Deo*
|
|
828
|
+
|
|
829
|
+
* Redis cache store is now compatible with redis-rb 5.0.
|
|
442
830
|
|
|
443
831
|
*Jean Boussier*
|
|
444
832
|
|
|
445
|
-
* Add `
|
|
446
|
-
sole item of the enumerable, raising if no items are found, or if more than
|
|
447
|
-
one is.
|
|
833
|
+
* Add `skip_nil:` support to `ActiveSupport::Cache::Store#fetch_multi`.
|
|
448
834
|
|
|
449
|
-
*
|
|
835
|
+
*Daniel Alfaro*
|
|
450
836
|
|
|
451
|
-
*
|
|
837
|
+
* Add `quarter` method to date/time
|
|
452
838
|
|
|
453
|
-
|
|
839
|
+
*Matt Swanson*
|
|
454
840
|
|
|
455
|
-
|
|
841
|
+
* Fix `NoMethodError` on custom `ActiveSupport::Deprecation` behavior.
|
|
456
842
|
|
|
457
|
-
|
|
843
|
+
`ActiveSupport::Deprecation.behavior=` was supposed to accept any object
|
|
844
|
+
that responds to `call`, but in fact its internal implementation assumed that
|
|
845
|
+
this object could respond to `arity`, so it was restricted to only `Proc` objects.
|
|
458
846
|
|
|
459
|
-
|
|
460
|
-
instance had fractional seconds the new UTC time instance was out by
|
|
461
|
-
a factor of 1,000,000 as the `Time.utc` constructor takes a usec
|
|
462
|
-
value and not a fractional second value.
|
|
847
|
+
This change removes this `arity` restriction of custom behaviors.
|
|
463
848
|
|
|
464
|
-
*
|
|
849
|
+
*Ryo Nakamura*
|
|
850
|
+
|
|
851
|
+
* Support `:url_safe` option for `MessageEncryptor`.
|
|
852
|
+
|
|
853
|
+
The `MessageEncryptor` constructor now accepts a `:url_safe` option, similar
|
|
854
|
+
to the `MessageVerifier` constructor. When enabled, this option ensures
|
|
855
|
+
that messages use a URL-safe encoding.
|
|
465
856
|
|
|
466
|
-
*
|
|
857
|
+
*Jonathan Hefner*
|
|
858
|
+
|
|
859
|
+
* Add `url_safe` option to `ActiveSupport::MessageVerifier` initializer
|
|
860
|
+
|
|
861
|
+
`ActiveSupport::MessageVerifier.new` now takes optional `url_safe` argument.
|
|
862
|
+
It can generate URL-safe strings by passing `url_safe: true`.
|
|
467
863
|
|
|
468
864
|
```ruby
|
|
469
|
-
|
|
865
|
+
verifier = ActiveSupport::MessageVerifier.new(url_safe: true)
|
|
866
|
+
message = verifier.generate(data) # => URL-safe string
|
|
470
867
|
```
|
|
471
868
|
|
|
472
|
-
|
|
869
|
+
This option is `false` by default to be backwards compatible.
|
|
473
870
|
|
|
474
|
-
*
|
|
871
|
+
*Shouichi Kamiya*
|
|
475
872
|
|
|
476
|
-
|
|
873
|
+
* Enable connection pooling by default for `MemCacheStore` and `RedisCacheStore`.
|
|
874
|
+
|
|
875
|
+
If you want to disable connection pooling, set `:pool` option to `false` when configuring the cache store:
|
|
876
|
+
|
|
877
|
+
```ruby
|
|
878
|
+
config.cache_store = :mem_cache_store, "cache.example.com", pool: false
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
*fatkodima*
|
|
477
882
|
|
|
478
|
-
*
|
|
479
|
-
is considerably faster.
|
|
883
|
+
* Add `force:` support to `ActiveSupport::Cache::Store#fetch_multi`.
|
|
480
884
|
|
|
481
|
-
|
|
885
|
+
*fatkodima*
|
|
886
|
+
|
|
887
|
+
* Deprecated `:pool_size` and `:pool_timeout` options for configuring connection pooling in cache stores.
|
|
888
|
+
|
|
889
|
+
Use `pool: true` to enable pooling with default settings:
|
|
482
890
|
|
|
483
891
|
```ruby
|
|
484
|
-
|
|
485
|
-
|
|
892
|
+
config.cache_store = :redis_cache_store, pool: true
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
Or pass individual options via `:pool` option:
|
|
486
896
|
|
|
487
|
-
|
|
488
|
-
|
|
897
|
+
```ruby
|
|
898
|
+
config.cache_store = :redis_cache_store, pool: { size: 10, timeout: 2 }
|
|
489
899
|
```
|
|
490
900
|
|
|
491
|
-
*
|
|
901
|
+
*fatkodima*
|
|
492
902
|
|
|
493
|
-
*
|
|
903
|
+
* Allow #increment and #decrement methods of `ActiveSupport::Cache::Store`
|
|
904
|
+
subclasses to set new values.
|
|
494
905
|
|
|
495
|
-
|
|
906
|
+
Previously incrementing or decrementing an unset key would fail and return
|
|
907
|
+
nil. A default will now be assumed and the key will be created.
|
|
496
908
|
|
|
497
|
-
*
|
|
909
|
+
*Andrej Blagojević*, *Eugene Kenny*
|
|
498
910
|
|
|
499
|
-
*
|
|
911
|
+
* Add `skip_nil:` support to `RedisCacheStore`
|
|
500
912
|
|
|
501
|
-
*
|
|
913
|
+
*Joey Paris*
|
|
502
914
|
|
|
503
|
-
*
|
|
504
|
-
|
|
915
|
+
* `ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true)` now
|
|
916
|
+
correctly writes expired keys.
|
|
505
917
|
|
|
506
|
-
|
|
507
|
-
payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
|
|
918
|
+
*Alan Savage*
|
|
508
919
|
|
|
509
|
-
|
|
510
|
-
payments.maximum(:price) # => 15
|
|
511
|
-
```
|
|
920
|
+
* `ActiveSupport::ErrorReporter` now accepts and forward a `source:` parameter.
|
|
512
921
|
|
|
513
|
-
This
|
|
514
|
-
|
|
922
|
+
This allow libraries to signal the origin of the errors, and reporters
|
|
923
|
+
to easily ignore some sources.
|
|
515
924
|
|
|
516
|
-
*
|
|
925
|
+
*Jean Boussier*
|
|
517
926
|
|
|
518
|
-
*
|
|
927
|
+
* Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
|
|
519
928
|
|
|
520
|
-
|
|
521
|
-
|
|
929
|
+
Add the method `ERB::Util.xml_name_escape` to escape dangerous characters
|
|
930
|
+
in names of tags and names of attributes, following the specification of XML.
|
|
522
931
|
|
|
523
|
-
|
|
932
|
+
*Álvaro Martín Fraguas*
|
|
524
933
|
|
|
525
|
-
|
|
934
|
+
* Respect `ActiveSupport::Logger.new`'s `:formatter` keyword argument
|
|
526
935
|
|
|
527
|
-
|
|
936
|
+
The stdlib `Logger::new` allows passing a `:formatter` keyword argument to
|
|
937
|
+
set the logger's formatter. Previously `ActiveSupport::Logger.new` ignored
|
|
938
|
+
that argument by always setting the formatter to an instance of
|
|
939
|
+
`ActiveSupport::Logger::SimpleFormatter`.
|
|
528
940
|
|
|
529
|
-
|
|
941
|
+
*Steven Harman*
|
|
530
942
|
|
|
531
|
-
|
|
532
|
-
```
|
|
943
|
+
* Deprecate preserving the pre-Ruby 2.4 behavior of `to_time`
|
|
533
944
|
|
|
534
|
-
|
|
945
|
+
With Ruby 2.4+ the default for +to_time+ changed from converting to the
|
|
946
|
+
local system time to preserving the offset of the receiver. At the time Rails
|
|
947
|
+
supported older versions of Ruby so a compatibility layer was added to assist
|
|
948
|
+
in the migration process. From Rails 5.0 new applications have defaulted to
|
|
949
|
+
the Ruby 2.4+ behavior and since Rails 7.0 now only supports Ruby 2.7+
|
|
950
|
+
this compatibility layer can be safely removed.
|
|
535
951
|
|
|
536
|
-
|
|
952
|
+
To minimize any noise generated the deprecation warning only appears when the
|
|
953
|
+
setting is configured to `false` as that is the only scenario where the
|
|
954
|
+
removal of the compatibility layer has any effect.
|
|
537
955
|
|
|
538
|
-
*
|
|
956
|
+
*Andrew White*
|
|
539
957
|
|
|
540
|
-
|
|
958
|
+
* `Pathname.blank?` only returns true for `Pathname.new("")`
|
|
541
959
|
|
|
542
|
-
|
|
543
|
-
|
|
960
|
+
Previously it would end up calling `Pathname#empty?` which returned true
|
|
961
|
+
if the path existed and was an empty directory or file.
|
|
544
962
|
|
|
545
|
-
|
|
963
|
+
That behavior was unlikely to be expected.
|
|
546
964
|
|
|
547
|
-
*
|
|
548
|
-
invalid.
|
|
965
|
+
*Jean Boussier*
|
|
549
966
|
|
|
550
|
-
|
|
967
|
+
* Deprecate `Notification::Event`'s `#children` and `#parent_of?`
|
|
551
968
|
|
|
552
|
-
*
|
|
969
|
+
*John Hawthorn*
|
|
553
970
|
|
|
554
|
-
|
|
971
|
+
* Change the default serializer of `ActiveSupport::MessageVerifier` from
|
|
972
|
+
`Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
|
|
555
973
|
|
|
556
|
-
|
|
974
|
+
Messages serialized with `Marshal` can still be read, but new messages will
|
|
975
|
+
be serialized with `ActiveSupport::JSON`. For more information, see
|
|
976
|
+
https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
|
|
557
977
|
|
|
558
|
-
*
|
|
978
|
+
*Saba Kiaei*, *David Buckley*, and *Jonathan Hefner*
|
|
559
979
|
|
|
560
|
-
*
|
|
980
|
+
* Change the default serializer of `ActiveSupport::MessageEncryptor` from
|
|
981
|
+
`Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
|
|
561
982
|
|
|
562
|
-
|
|
983
|
+
Messages serialized with `Marshal` can still be read, but new messages will
|
|
984
|
+
be serialized with `ActiveSupport::JSON`. For more information, see
|
|
985
|
+
https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
|
|
563
986
|
|
|
987
|
+
*Zack Deveau*, *Martin Gingras*, and *Jonathan Hefner*
|
|
988
|
+
|
|
989
|
+
* Add `ActiveSupport::TestCase#stub_const` to stub a constant for the duration of a yield.
|
|
990
|
+
|
|
991
|
+
*DHH*
|
|
992
|
+
|
|
993
|
+
* Fix `ActiveSupport::EncryptedConfiguration` to be compatible with Psych 4
|
|
994
|
+
|
|
995
|
+
*Stephen Sugden*
|
|
996
|
+
|
|
997
|
+
* Improve `File.atomic_write` error handling
|
|
998
|
+
|
|
999
|
+
*Daniel Pepper*
|
|
1000
|
+
|
|
1001
|
+
* Fix `Class#descendants` and `DescendantsTracker#descendants` compatibility with Ruby 3.1.
|
|
1002
|
+
|
|
1003
|
+
[The native `Class#descendants` was reverted prior to Ruby 3.1 release](https://bugs.ruby-lang.org/issues/14394#note-33),
|
|
1004
|
+
but `Class#subclasses` was kept, breaking the feature detection.
|
|
1005
|
+
|
|
1006
|
+
*Jean Boussier*
|
|
564
1007
|
|
|
565
|
-
Please check [
|
|
1008
|
+
Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activesupport/CHANGELOG.md) for previous changes.
|