activesupport 7.1.5.2 → 8.1.2.1
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 +288 -1068
- data/README.rdoc +1 -1
- data/lib/active_support/array_inquirer.rb +1 -1
- data/lib/active_support/backtrace_cleaner.rb +81 -3
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +65 -78
- data/lib/active_support/cache/file_store.rb +29 -14
- data/lib/active_support/cache/mem_cache_store.rb +43 -103
- data/lib/active_support/cache/memory_store.rb +13 -6
- data/lib/active_support/cache/null_store.rb +2 -2
- data/lib/active_support/cache/redis_cache_store.rb +59 -47
- data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
- data/lib/active_support/cache/strategy/local_cache.rb +72 -27
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
- data/lib/active_support/cache.rb +146 -86
- data/lib/active_support/callbacks.rb +102 -126
- data/lib/active_support/class_attribute.rb +33 -0
- data/lib/active_support/code_generator.rb +9 -0
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +8 -62
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/concurrency/thread_monitor.rb +55 -0
- data/lib/active_support/configurable.rb +34 -0
- data/lib/active_support/configuration_file.rb +15 -6
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/array/conversions.rb +3 -5
- data/lib/active_support/core_ext/array.rb +7 -7
- data/lib/active_support/core_ext/benchmark.rb +4 -14
- data/lib/active_support/core_ext/big_decimal.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +26 -20
- data/lib/active_support/core_ext/class/subclasses.rb +15 -35
- data/lib/active_support/core_ext/class.rb +2 -2
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/conversions.rb +2 -2
- data/lib/active_support/core_ext/date.rb +5 -5
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -9
- data/lib/active_support/core_ext/date_time/blank.rb +4 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +4 -6
- data/lib/active_support/core_ext/date_time.rb +5 -5
- data/lib/active_support/core_ext/digest/uuid.rb +6 -0
- data/lib/active_support/core_ext/digest.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +25 -8
- data/lib/active_support/core_ext/erb/util.rb +10 -5
- data/lib/active_support/core_ext/file.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
- data/lib/active_support/core_ext/hash/except.rb +0 -12
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/hash.rb +8 -8
- data/lib/active_support/core_ext/integer.rb +3 -3
- data/lib/active_support/core_ext/kernel.rb +3 -3
- data/lib/active_support/core_ext/module/attr_internal.rb +16 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -163
- data/lib/active_support/core_ext/module/deprecation.rb +1 -4
- data/lib/active_support/core_ext/module/introspection.rb +3 -0
- data/lib/active_support/core_ext/module.rb +11 -11
- data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
- data/lib/active_support/core_ext/numeric.rb +3 -3
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
- data/lib/active_support/core_ext/object/json.rb +25 -12
- data/lib/active_support/core_ext/object/to_query.rb +7 -1
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/object/with.rb +5 -3
- data/lib/active_support/core_ext/object.rb +13 -13
- data/lib/active_support/core_ext/pathname/blank.rb +4 -0
- data/lib/active_support/core_ext/pathname.rb +2 -2
- data/lib/active_support/core_ext/range/overlap.rb +4 -4
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +4 -4
- data/lib/active_support/core_ext/securerandom.rb +4 -4
- data/lib/active_support/core_ext/string/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +4 -4
- data/lib/active_support/core_ext/string/multibyte.rb +13 -4
- data/lib/active_support/core_ext/string/output_safety.rb +29 -20
- data/lib/active_support/core_ext/string.rb +13 -13
- data/lib/active_support/core_ext/symbol.rb +1 -1
- data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
- data/lib/active_support/core_ext/time/calculations.rb +25 -30
- data/lib/active_support/core_ext/time/compatibility.rb +2 -3
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +1 -1
- data/lib/active_support/core_ext/time.rb +5 -5
- data/lib/active_support/core_ext.rb +1 -2
- data/lib/active_support/current_attributes/test_helper.rb +2 -2
- data/lib/active_support/current_attributes.rb +58 -50
- data/lib/active_support/delegation.rb +183 -0
- data/lib/active_support/dependencies/autoload.rb +0 -12
- data/lib/active_support/dependencies/interlock.rb +11 -5
- data/lib/active_support/dependencies.rb +6 -2
- data/lib/active_support/deprecation/constant_accessor.rb +47 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
- data/lib/active_support/deprecation/reporting.rb +5 -17
- data/lib/active_support/deprecation.rb +8 -5
- data/lib/active_support/descendants_tracker.rb +9 -87
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -2
- data/lib/active_support/duration.rb +25 -16
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/encrypted_configuration.rb +20 -2
- data/lib/active_support/encrypted_file.rb +1 -1
- data/lib/active_support/error_reporter.rb +121 -6
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +592 -0
- data/lib/active_support/evented_file_update_checker.rb +5 -3
- data/lib/active_support/execution_context.rb +64 -7
- data/lib/active_support/execution_wrapper.rb +1 -2
- data/lib/active_support/file_update_checker.rb +9 -7
- data/lib/active_support/fork_tracker.rb +2 -38
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/gzip.rb +1 -0
- data/lib/active_support/hash_with_indifferent_access.rb +66 -45
- data/lib/active_support/html_safe_translation.rb +3 -0
- data/lib/active_support/i18n_railtie.rb +19 -11
- data/lib/active_support/inflector/inflections.rb +32 -15
- data/lib/active_support/inflector/methods.rb +2 -2
- data/lib/active_support/inflector/transliterate.rb +6 -8
- data/lib/active_support/isolated_execution_state.rb +17 -17
- data/lib/active_support/json/decoding.rb +6 -4
- data/lib/active_support/json/encoding.rb +157 -21
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/log_subscriber.rb +2 -18
- data/lib/active_support/logger.rb +15 -2
- data/lib/active_support/logger_thread_safe_level.rb +4 -9
- data/lib/active_support/message_encryptors.rb +54 -2
- data/lib/active_support/message_pack/extensions.rb +21 -3
- data/lib/active_support/message_verifier.rb +21 -0
- data/lib/active_support/message_verifiers.rb +57 -3
- data/lib/active_support/messages/rotation_coordinator.rb +9 -0
- data/lib/active_support/messages/rotator.rb +10 -0
- data/lib/active_support/multibyte/chars.rb +14 -4
- data/lib/active_support/multibyte.rb +4 -0
- data/lib/active_support/notifications/fanout.rb +68 -50
- data/lib/active_support/notifications/instrumenter.rb +22 -19
- data/lib/active_support/notifications.rb +28 -27
- data/lib/active_support/number_helper/number_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +17 -2
- data/lib/active_support/number_helper.rb +22 -0
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_options.rb +53 -15
- data/lib/active_support/railtie.rb +36 -20
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/structured_event_subscriber.rb +99 -0
- data/lib/active_support/subscriber.rb +1 -5
- data/lib/active_support/syntax_error_proxy.rb +7 -0
- data/lib/active_support/tagged_logging.rb +5 -1
- data/lib/active_support/test_case.rb +69 -6
- data/lib/active_support/testing/assertions.rb +115 -27
- data/lib/active_support/testing/autorun.rb +5 -0
- data/lib/active_support/testing/constant_stubbing.rb +30 -8
- data/lib/active_support/testing/deprecation.rb +5 -12
- data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
- data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
- data/lib/active_support/testing/isolation.rb +19 -9
- data/lib/active_support/testing/method_call_assertions.rb +2 -16
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/server.rb +18 -2
- data/lib/active_support/testing/parallelization/worker.rb +8 -4
- data/lib/active_support/testing/parallelization.rb +25 -1
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +11 -6
- data/lib/active_support/time_with_zone.rb +44 -27
- data/lib/active_support/values/time_zone.rb +26 -17
- data/lib/active_support/xml_mini.rb +14 -4
- data/lib/active_support.rb +22 -9
- metadata +32 -18
- data/lib/active_support/core_ext/range/each.rb +0 -24
- data/lib/active_support/deprecation/instance_delegator.rb +0 -65
- data/lib/active_support/proxy_object.rb +0 -17
- data/lib/active_support/ruby_features.rb +0 -7
- data/lib/active_support/testing/strict_warnings.rb +0 -39
data/CHANGELOG.md
CHANGED
|
@@ -1,1306 +1,526 @@
|
|
|
1
|
-
## Rails
|
|
1
|
+
## Rails 8.1.2.1 (March 23, 2026) ##
|
|
2
2
|
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Rails 7.1.5.1 (December 10, 2024) ##
|
|
7
|
-
|
|
8
|
-
* No changes.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Rails 7.1.5 (October 30, 2024) ##
|
|
12
|
-
|
|
13
|
-
* No changes.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
## Rails 7.1.4.2 (October 23, 2024) ##
|
|
17
|
-
|
|
18
|
-
* No changes.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## Rails 7.1.4.1 (October 15, 2024) ##
|
|
22
|
-
|
|
23
|
-
* No changes.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
## Rails 7.1.4 (August 22, 2024) ##
|
|
27
|
-
|
|
28
|
-
* Improve compatibility for `ActiveSupport::BroadcastLogger`.
|
|
29
|
-
|
|
30
|
-
*Máximo Mussini*
|
|
31
|
-
|
|
32
|
-
* Pass options along to write_entry in handle_expired_entry method.
|
|
33
|
-
|
|
34
|
-
*Graham Cooper*
|
|
35
|
-
|
|
36
|
-
* Fix Active Support configurations deprecations.
|
|
3
|
+
* Reject scientific notation in NumberConverter
|
|
37
4
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* Fix teardown callbacks.
|
|
41
|
-
|
|
42
|
-
*Tristan Starck*
|
|
43
|
-
|
|
44
|
-
* `BacktraceCleaner` silence core internal methods by default.
|
|
45
|
-
|
|
46
|
-
*Jean Boussier*
|
|
47
|
-
|
|
48
|
-
* Fix `delegate_missing_to allow_nil: true` when called with implict self
|
|
49
|
-
|
|
50
|
-
```ruby
|
|
51
|
-
class Person
|
|
52
|
-
delegate_missing_to :address, allow_nil: true
|
|
53
|
-
|
|
54
|
-
def address
|
|
55
|
-
nil
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def berliner?
|
|
59
|
-
city == "Berlin"
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
Person.new.city # => nil
|
|
64
|
-
Person.new.berliner? # undefined local variable or method `city' for an instance of Person (NameError)
|
|
65
|
-
```
|
|
5
|
+
[CVE-2026-33176]
|
|
66
6
|
|
|
67
7
|
*Jean Boussier*
|
|
68
8
|
|
|
69
|
-
*
|
|
70
|
-
|
|
71
|
-
This would happen if using `TaggerLogger` with a Proc
|
|
72
|
-
formatter on which you called `object_id`.
|
|
9
|
+
* Fix `SafeBuffer#%` to preserve unsafe status
|
|
73
10
|
|
|
74
|
-
|
|
75
|
-
[BUG] Object ID seen, but not in mapping table: proc
|
|
76
|
-
```
|
|
11
|
+
[CVE-2026-33170]
|
|
77
12
|
|
|
78
13
|
*Jean Boussier*
|
|
79
14
|
|
|
80
|
-
*
|
|
15
|
+
* Improve performance of NumberToDelimitedConverter
|
|
81
16
|
|
|
82
|
-
|
|
83
|
-
asynchronous queries (by a factor `1000`).
|
|
17
|
+
[CVE-2026-33169]
|
|
84
18
|
|
|
85
19
|
*Jean Boussier*
|
|
86
20
|
|
|
87
21
|
|
|
88
|
-
## Rails
|
|
89
|
-
|
|
90
|
-
* No changes.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
## Rails 7.1.3.3 (May 16, 2024) ##
|
|
94
|
-
|
|
95
|
-
* No changes.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
## Rails 7.1.3.2 (February 21, 2024) ##
|
|
99
|
-
|
|
100
|
-
* No changes.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
## Rails 7.1.3.1 (February 21, 2024) ##
|
|
104
|
-
|
|
105
|
-
* No changes.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
## Rails 7.1.3 (January 16, 2024) ##
|
|
109
|
-
|
|
110
|
-
* Handle nil `backtrace_locations` in `ActiveSupport::SyntaxErrorProxy`.
|
|
111
|
-
|
|
112
|
-
*Eugene Kenny*
|
|
113
|
-
|
|
114
|
-
* Fix `ActiveSupport::JSON.encode` to prevent duplicate keys.
|
|
115
|
-
|
|
116
|
-
If the same key exist in both String and Symbol form it could
|
|
117
|
-
lead to the same key being emitted twice.
|
|
118
|
-
|
|
119
|
-
*Manish Sharma*
|
|
120
|
-
|
|
121
|
-
* Fix `ActiveSupport::Cache::Store#read_multi` when using a cache namespace
|
|
122
|
-
and local cache strategy.
|
|
123
|
-
|
|
124
|
-
*Mark Oleson*
|
|
125
|
-
|
|
126
|
-
* Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
|
|
127
|
-
|
|
128
|
-
There is a bug in the current implementation of #travel_to:
|
|
129
|
-
it remembers a timezone of its argument, and all stubbed methods start
|
|
130
|
-
returning results in that remembered timezone. However, the expected
|
|
131
|
-
behaviour is to return results in a system timezone.
|
|
132
|
-
|
|
133
|
-
*Aleksei Chernenkov*
|
|
134
|
-
|
|
135
|
-
* Fix `:unless_exist` option for `MemoryStore#write` (et al) when using a
|
|
136
|
-
cache namespace.
|
|
137
|
-
|
|
138
|
-
*S. Brent Faulkner*
|
|
139
|
-
|
|
140
|
-
* Fix ActiveSupport::Deprecation to handle blaming generated code.
|
|
22
|
+
## Rails 8.1.2 (January 08, 2026) ##
|
|
141
23
|
|
|
142
|
-
|
|
24
|
+
* Make `delegate` and `delegate_missing_to` work in BasicObject subclasses.
|
|
143
25
|
|
|
26
|
+
*Rafael Mendonça França*
|
|
144
27
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* Fix `:expires_in` option for `RedisCacheStore#write_multi`.
|
|
148
|
-
|
|
149
|
-
*fatkodima*
|
|
150
|
-
|
|
151
|
-
* Fix deserialization of non-string "purpose" field in Message serializer
|
|
152
|
-
|
|
153
|
-
*Jacopo Beschi*
|
|
154
|
-
|
|
155
|
-
* Prevent global cache options being overwritten when setting dynamic options
|
|
156
|
-
inside a `ActiveSupport::Cache::Store#fetch` block.
|
|
157
|
-
|
|
158
|
-
*Yasha Krasnou*
|
|
159
|
-
|
|
160
|
-
* Fix missing `require` resulting in `NoMethodError` when running
|
|
161
|
-
`bin/rails secrets:show` or `bin/rails secrets:edit`.
|
|
162
|
-
|
|
163
|
-
*Stephen Ierodiaconou*
|
|
164
|
-
|
|
165
|
-
* Ensure `{down,up}case_first` returns non-frozen string.
|
|
166
|
-
|
|
167
|
-
*Jonathan Hefner*
|
|
168
|
-
|
|
169
|
-
* Fix `#to_fs(:human_size)` to correctly work with negative numbers.
|
|
170
|
-
|
|
171
|
-
*Earlopain*
|
|
172
|
-
|
|
173
|
-
* Fix `BroadcastLogger#dup` so that it duplicates the logger's `broadcasts`.
|
|
174
|
-
|
|
175
|
-
*Andrew Novoselac*
|
|
28
|
+
* Fix Inflectors when using a locale that fallbacks to `:en`.
|
|
176
29
|
|
|
177
|
-
*
|
|
30
|
+
*Said Kaldybaev*
|
|
178
31
|
|
|
179
|
-
|
|
32
|
+
* Fix `ActiveSupport::TimeWithZone#as_json` to consistently return UTF-8 strings.
|
|
180
33
|
|
|
181
|
-
|
|
34
|
+
Previously the returned string would sometime be encoded in US-ASCII, which in
|
|
35
|
+
some cases may be problematic.
|
|
182
36
|
|
|
183
|
-
|
|
184
|
-
deserialized as a cache miss. It fail to do so for compressed payload in the Rails 6.1
|
|
185
|
-
legacy format.
|
|
37
|
+
Now the method consistently always return UTF-8 strings.
|
|
186
38
|
|
|
187
39
|
*Jean Boussier*
|
|
188
40
|
|
|
189
|
-
* Fix `
|
|
190
|
-
|
|
191
|
-
*fatkodima*
|
|
192
|
-
|
|
193
|
-
* Fix time travel helpers to work when nested using with separate classes.
|
|
194
|
-
|
|
195
|
-
*fatkodima*
|
|
196
|
-
|
|
197
|
-
* Fix `delete_matched` for file cache store to work with keys longer than the
|
|
198
|
-
max filename size.
|
|
41
|
+
* Fix `TimeWithZone#xmlschema` when wrapping a `DateTime` instance in local time.
|
|
199
42
|
|
|
200
|
-
|
|
43
|
+
Previously it would return an invalid time.
|
|
201
44
|
|
|
202
|
-
*
|
|
45
|
+
*Dmytro Rymar*
|
|
203
46
|
|
|
204
|
-
|
|
205
|
-
|
|
47
|
+
* Implement LocalCache strategy on `ActiveSupport::Cache::MemoryStore`. The memory store
|
|
48
|
+
needs to respond to the same interface as other cache stores (e.g. `ActiveSupport::NullStore`).
|
|
206
49
|
|
|
207
|
-
|
|
208
|
-
`SemanticLogger` instance.
|
|
50
|
+
*Mikey Gough*
|
|
209
51
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
## Rails 7.1.1 (October 11, 2023) ##
|
|
213
|
-
|
|
214
|
-
* Add support for keyword arguments when delegating calls to custom loggers from `ActiveSupport::BroadcastLogger`.
|
|
215
|
-
|
|
216
|
-
*Edouard Chin*
|
|
217
|
-
|
|
218
|
-
* `NumberHelper`: handle objects responding `to_d`.
|
|
219
|
-
|
|
220
|
-
*fatkodima*
|
|
221
|
-
|
|
222
|
-
* Fix RedisCacheStore to properly set the TTL when incrementing or decrementing.
|
|
223
|
-
|
|
224
|
-
This bug was only impacting Redis server older than 7.0.
|
|
225
|
-
|
|
226
|
-
*Thomas Countz*
|
|
227
|
-
|
|
228
|
-
* Fix MemoryStore to prevent race conditions when incrementing or decrementing.
|
|
229
|
-
|
|
230
|
-
*Pierre Jambet*
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
## Rails 7.1.0 (October 05, 2023) ##
|
|
234
|
-
|
|
235
|
-
* No changes.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
## Rails 7.1.0.rc2 (October 01, 2023) ##
|
|
239
|
-
|
|
240
|
-
* Fix `AS::MessagePack` with `ENV["RAILS_MAX_THREADS"]`.
|
|
241
|
-
|
|
242
|
-
*Jonathan Hefner*
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
## Rails 7.1.0.rc1 (September 27, 2023) ##
|
|
246
|
-
|
|
247
|
-
* Add a new public API for broadcasting logs
|
|
248
|
-
|
|
249
|
-
This feature existed for a while but was until now a private API.
|
|
250
|
-
Broadcasting log allows to send log message to difference sinks (STDOUT, a file ...) and
|
|
251
|
-
is used by default in the development environment to write logs both on STDOUT and in the
|
|
252
|
-
"development.log" file.
|
|
253
|
-
|
|
254
|
-
Basic usage:
|
|
52
|
+
* Fix `ActiveSupport::Inflector.humanize` with international characters.
|
|
255
53
|
|
|
256
54
|
```ruby
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger, file_logger)
|
|
260
|
-
|
|
261
|
-
broadcast.info("Hello!") # The "Hello!" message is written on STDOUT and in the log file.
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
Adding other sink(s) to the broadcast:
|
|
265
|
-
|
|
266
|
-
```ruby
|
|
267
|
-
broadcast = ActiveSupport::BroadcastLogger.new
|
|
268
|
-
broadcast.broadcast_to(Logger.new(STDERR))
|
|
55
|
+
ActiveSupport::Inflector.humanize("áÉÍÓÚ") # => "Áéíóú"
|
|
56
|
+
ActiveSupport::Inflector.humanize("аБВГДЕ") # => "Абвгде"
|
|
269
57
|
```
|
|
270
58
|
|
|
271
|
-
|
|
59
|
+
*Jose Luis Duran*
|
|
272
60
|
|
|
273
|
-
```ruby
|
|
274
|
-
stdout_logger = Logger.new(STDOUT)
|
|
275
|
-
broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger)
|
|
276
61
|
|
|
277
|
-
|
|
278
|
-
```
|
|
62
|
+
## Rails 8.1.1 (October 28, 2025) ##
|
|
279
63
|
|
|
280
|
-
|
|
64
|
+
* No changes.
|
|
281
65
|
|
|
282
|
-
* Fix Range#overlap? not taking empty ranges into account on Ruby < 3.3
|
|
283
66
|
|
|
284
|
-
|
|
67
|
+
## Rails 8.1.0 (October 22, 2025) ##
|
|
285
68
|
|
|
286
|
-
*
|
|
69
|
+
* Remove deprecated passing a Time object to `Time#since`.
|
|
287
70
|
|
|
288
|
-
*
|
|
71
|
+
*Rafael Mendonça França*
|
|
289
72
|
|
|
73
|
+
* Remove deprecated `Benchmark.ms` method. It is now defined in the `benchmark` gem.
|
|
290
74
|
|
|
291
|
-
|
|
75
|
+
*Rafael Mendonça França*
|
|
292
76
|
|
|
293
|
-
*
|
|
77
|
+
* Remove deprecated addition for `Time` instances with `ActiveSupport::TimeWithZone`.
|
|
294
78
|
|
|
295
|
-
|
|
296
|
-
Ruby 2.7 and 3.0 users who want `bigdecimal` version 2.0.0 or 3.0.0 behavior as a default gem,
|
|
297
|
-
pin the `bigdecimal` version in your application Gemfile.
|
|
79
|
+
*Rafael Mendonça França*
|
|
298
80
|
|
|
299
|
-
|
|
81
|
+
* Remove deprecated support for `to_time` to preserve the system local time. It will now always preserve the receiver
|
|
82
|
+
timezone.
|
|
300
83
|
|
|
301
|
-
*
|
|
84
|
+
*Rafael Mendonça França*
|
|
302
85
|
|
|
303
|
-
|
|
86
|
+
* Deprecate `config.active_support.to_time_preserves_timezone`.
|
|
304
87
|
|
|
305
|
-
*
|
|
306
|
-
version-mismatched cache entries can now be detected without deserializing
|
|
307
|
-
their values.
|
|
88
|
+
*Rafael Mendonça França*
|
|
308
89
|
|
|
309
|
-
|
|
90
|
+
* Standardize event name formatting in `assert_event_reported` error messages.
|
|
310
91
|
|
|
311
|
-
|
|
92
|
+
The event name in failure messages now uses `.inspect` (e.g., `name: "user.created"`)
|
|
93
|
+
to match `assert_events_reported` and provide type clarity between strings and symbols.
|
|
94
|
+
This only affects tests that assert on the failure message format itself.
|
|
312
95
|
|
|
313
|
-
|
|
314
|
-
exists and `0` otherwise. Now it returns true if the entry exists and false
|
|
315
|
-
otherwise, just like the other stores.
|
|
96
|
+
*George Ma*
|
|
316
97
|
|
|
317
|
-
|
|
318
|
-
`false` now as well.
|
|
98
|
+
* Fix `Enumerable#sole` to return the full tuple instead of just the first element of the tuple.
|
|
319
99
|
|
|
320
|
-
*
|
|
100
|
+
*Olivier Bellone*
|
|
321
101
|
|
|
322
|
-
*
|
|
323
|
-
a `:compressor` option. The specified compressor must respond to `deflate`
|
|
324
|
-
and `inflate`. For example:
|
|
102
|
+
* Fix parallel tests hanging when worker processes die abruptly.
|
|
325
103
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
def self.deflate(string)
|
|
329
|
-
# compression logic...
|
|
330
|
-
end
|
|
104
|
+
Previously, if a worker process was killed (e.g., OOM killed, `kill -9`) during parallel
|
|
105
|
+
test execution, the test suite would hang forever waiting for the dead worker.
|
|
331
106
|
|
|
332
|
-
|
|
333
|
-
# decompression logic...
|
|
334
|
-
end
|
|
335
|
-
end
|
|
107
|
+
*Joshua Young*
|
|
336
108
|
|
|
337
|
-
|
|
338
|
-
```
|
|
109
|
+
* Add `config.active_support.escape_js_separators_in_json`.
|
|
339
110
|
|
|
340
|
-
|
|
111
|
+
Introduce a new framework default to skip escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON.
|
|
341
112
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
serializers are only responsible for serializing a cached value, whereas
|
|
345
|
-
coders are responsible for serializing the entire `ActiveSupport::Cache::Entry`
|
|
346
|
-
instance. Additionally, the output from serializers can be automatically
|
|
347
|
-
compressed, whereas coders are responsible for their own compression.
|
|
113
|
+
Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019.
|
|
114
|
+
As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset.
|
|
348
115
|
|
|
349
|
-
|
|
350
|
-
optimizations, including the bare string optimization introduced by cache
|
|
351
|
-
format version 7.1.
|
|
116
|
+
*Étienne Barrié*, *Jean Boussier*
|
|
352
117
|
|
|
353
|
-
|
|
354
|
-
both will raise an `ArgumentError`.
|
|
118
|
+
* Fix `NameError` when `class_attribute` is defined on instance singleton classes.
|
|
355
119
|
|
|
356
|
-
|
|
120
|
+
Previously, calling `class_attribute` on an instance's singleton class would raise
|
|
121
|
+
a `NameError` when accessing the attribute through the instance.
|
|
357
122
|
|
|
358
|
-
|
|
123
|
+
```ruby
|
|
124
|
+
object = MyClass.new
|
|
125
|
+
object.singleton_class.class_attribute :foo, default: "bar"
|
|
126
|
+
object.foo # previously raised NameError, now returns "bar"
|
|
127
|
+
```
|
|
359
128
|
|
|
360
|
-
*
|
|
129
|
+
*Joshua Young*
|
|
361
130
|
|
|
362
|
-
*
|
|
131
|
+
* Introduce `ActiveSupport::Testing::EventReporterAssertions#with_debug_event_reporting`
|
|
132
|
+
to enable event reporter debug mode in tests.
|
|
363
133
|
|
|
364
|
-
|
|
134
|
+
The previous way to enable debug mode is by using `#with_debug` on the
|
|
135
|
+
event reporter itself, which is too verbose. This new helper will help
|
|
136
|
+
clear up any confusion on how to test debug events.
|
|
365
137
|
|
|
366
|
-
|
|
367
|
-
ActiveSupport::KeyGenerator.new(secret).inspect
|
|
368
|
-
"#<ActiveSupport::KeyGenerator:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
|
|
369
|
-
```
|
|
138
|
+
*Gannon McGibbon*
|
|
370
139
|
|
|
371
|
-
|
|
140
|
+
* Add `ActiveSupport::StructuredEventSubscriber` for consuming notifications and
|
|
141
|
+
emitting structured event logs. Events may be emitted with the `#emit_event`
|
|
142
|
+
or `#emit_debug_event` methods.
|
|
372
143
|
|
|
373
144
|
```ruby
|
|
374
|
-
ActiveSupport::
|
|
375
|
-
|
|
145
|
+
class MyStructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber
|
|
146
|
+
def notification(event)
|
|
147
|
+
emit_event("my.notification", data: 1)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
376
150
|
```
|
|
377
151
|
|
|
378
|
-
*
|
|
379
|
-
|
|
380
|
-
* Improve error message when EventedFileUpdateChecker is used without a
|
|
381
|
-
compatible version of the Listen gem
|
|
152
|
+
*Adrianna Chang*
|
|
382
153
|
|
|
383
|
-
|
|
154
|
+
* `ActiveSupport::FileUpdateChecker` does not depend on `Time.now` to prevent unecessary reloads with time travel test helpers
|
|
384
155
|
|
|
385
|
-
*
|
|
156
|
+
*Jan Grodowski*
|
|
386
157
|
|
|
387
|
-
|
|
388
|
-
reporter to report deprecation warnings to `ActiveSupport::ErrorReporter`.
|
|
158
|
+
* Add `ActiveSupport::Cache::Store#namespace=` and `#namespace`.
|
|
389
159
|
|
|
390
|
-
|
|
160
|
+
Can be used as an alternative to `Store#clear` in some situations such as parallel
|
|
161
|
+
testing.
|
|
391
162
|
|
|
392
|
-
|
|
163
|
+
*Nick Schwaderer*
|
|
393
164
|
|
|
394
|
-
|
|
165
|
+
* Create `parallel_worker_id` helper for running parallel tests. This allows users to
|
|
166
|
+
know which worker they are currently running in.
|
|
395
167
|
|
|
396
|
-
*
|
|
168
|
+
*Nick Schwaderer*
|
|
397
169
|
|
|
398
|
-
|
|
170
|
+
* Make the cache of `ActiveSupport::Cache::Strategy::LocalCache::Middleware` updatable.
|
|
399
171
|
|
|
400
|
-
|
|
401
|
-
|
|
172
|
+
If the cache client at `Rails.cache` of a booted application changes, the corresponding
|
|
173
|
+
mounted middleware needs to update in order for request-local caches to be setup properly.
|
|
174
|
+
Otherwise, redundant cache operations will erroneously hit the datastore.
|
|
402
175
|
|
|
403
|
-
*
|
|
404
|
-
|
|
405
|
-
* Don't show secrets for `MessageEncryptor#inspect`.
|
|
406
|
-
|
|
407
|
-
Before:
|
|
176
|
+
*Gannon McGibbon*
|
|
408
177
|
|
|
409
|
-
|
|
410
|
-
ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
|
|
411
|
-
"#<ActiveSupport::MessageEncryptor:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
|
|
412
|
-
```
|
|
178
|
+
* Add `assert_events_reported` test helper for `ActiveSupport::EventReporter`.
|
|
413
179
|
|
|
414
|
-
|
|
180
|
+
This new assertion allows testing multiple events in a single block, regardless of order:
|
|
415
181
|
|
|
416
182
|
```ruby
|
|
417
|
-
|
|
418
|
-
|
|
183
|
+
assert_events_reported([
|
|
184
|
+
{ name: "user.created", payload: { id: 123 } },
|
|
185
|
+
{ name: "email.sent", payload: { to: "user@example.com" } }
|
|
186
|
+
]) do
|
|
187
|
+
create_user_and_send_welcome_email
|
|
188
|
+
end
|
|
419
189
|
```
|
|
420
190
|
|
|
421
|
-
*
|
|
191
|
+
*George Ma*
|
|
422
192
|
|
|
423
|
-
*
|
|
193
|
+
* Add `ActiveSupport::TimeZone#standard_name` method.
|
|
424
194
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
After:
|
|
432
|
-
```ruby
|
|
433
|
-
Rails.application.credentials.inspect
|
|
434
|
-
"#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8>"
|
|
195
|
+
``` ruby
|
|
196
|
+
zone = ActiveSupport::TimeZone['Hawaii']
|
|
197
|
+
# Old way
|
|
198
|
+
ActiveSupport::TimeZone::MAPPING[zone.name]
|
|
199
|
+
# New way
|
|
200
|
+
zone.standard_name # => 'Pacific/Honolulu'
|
|
435
201
|
```
|
|
436
202
|
|
|
437
|
-
*
|
|
438
|
-
|
|
439
|
-
* `ERB::Util.html_escape_once` always returns an `html_safe` string.
|
|
440
|
-
|
|
441
|
-
This method previously maintained the `html_safe?` property of a string on the return
|
|
442
|
-
value. Because this string has been escaped, however, not marking it as `html_safe` causes
|
|
443
|
-
entities to be double-escaped.
|
|
203
|
+
*Bogdan Gusiev*
|
|
444
204
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
```html
|
|
448
|
-
<p><%= html_escape_once("this & that & the other") %></p>
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
Before this change, that would be double-escaped and render as:
|
|
452
|
-
|
|
453
|
-
```html
|
|
454
|
-
<p>this &amp; that &amp; the other</p>
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
After this change, it renders correctly as:
|
|
458
|
-
|
|
459
|
-
```html
|
|
460
|
-
<p>this & that & the other</p>
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
Fixes #48256
|
|
464
|
-
|
|
465
|
-
*Mike Dalessio*
|
|
466
|
-
|
|
467
|
-
* Deprecate `SafeBuffer#clone_empty`.
|
|
468
|
-
|
|
469
|
-
This method has not been used internally since Rails 4.2.0.
|
|
470
|
-
|
|
471
|
-
*Mike Dalessio*
|
|
205
|
+
* Add Structured Event Reporter, accessible via `Rails.event`.
|
|
472
206
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
These serializers require the [`msgpack` gem](https://rubygems.org/gems/msgpack)
|
|
476
|
-
(>= 1.7.0).
|
|
477
|
-
|
|
478
|
-
The Message Pack format can provide improved performance and smaller payload
|
|
479
|
-
sizes. It also supports round-tripping some Ruby types that are not supported
|
|
480
|
-
by JSON. For example:
|
|
481
|
-
|
|
482
|
-
```ruby
|
|
483
|
-
verifier = ActiveSupport::MessageVerifier.new("secret")
|
|
484
|
-
data = [{ a: 1 }, { b: 2 }.with_indifferent_access, 1.to_d, Time.at(0, 123)]
|
|
485
|
-
message = verifier.generate(data)
|
|
486
|
-
|
|
487
|
-
# BEFORE with config.active_support.message_serializer = :json
|
|
488
|
-
verifier.verified(message)
|
|
489
|
-
# => [{"a"=>1}, {"b"=>2}, "1.0", "1969-12-31T18:00:00.000-06:00"]
|
|
490
|
-
verifier.verified(message).map(&:class)
|
|
491
|
-
# => [Hash, Hash, String, String]
|
|
492
|
-
|
|
493
|
-
# AFTER with config.active_support.message_serializer = :message_pack
|
|
494
|
-
verifier.verified(message)
|
|
495
|
-
# => [{:a=>1}, {"b"=>2}, 0.1e1, 1969-12-31 18:00:00.000123 -0600]
|
|
496
|
-
verifier.verified(message).map(&:class)
|
|
497
|
-
# => [Hash, ActiveSupport::HashWithIndifferentAccess, BigDecimal, Time]
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
The `:message_pack` serializer can fall back to deserializing with
|
|
501
|
-
`ActiveSupport::JSON` when necessary, and the `:message_pack_allow_marshal`
|
|
502
|
-
serializer can fall back to deserializing with `Marshal` as well as
|
|
503
|
-
`ActiveSupport::JSON`. Additionally, the `:marshal`, `:json`, and
|
|
504
|
-
`:json_allow_marshal` serializers can now fall back to deserializing with
|
|
505
|
-
`ActiveSupport::MessagePack` when necessary. These behaviors ensure old
|
|
506
|
-
messages can still be read so that migration is easier.
|
|
507
|
-
|
|
508
|
-
*Jonathan Hefner*
|
|
509
|
-
|
|
510
|
-
* A new `7.1` cache format is available which includes an optimization for
|
|
511
|
-
bare string values such as view fragments.
|
|
512
|
-
|
|
513
|
-
The `7.1` cache format is used by default for new apps, and existing apps
|
|
514
|
-
can enable the format by setting `config.load_defaults 7.1` or by setting
|
|
515
|
-
`config.active_support.cache_format_version = 7.1` in `config/application.rb`
|
|
516
|
-
or a `config/environments/*.rb` file.
|
|
517
|
-
|
|
518
|
-
Cache entries written using the `6.1` or `7.0` cache formats can be read
|
|
519
|
-
when using the `7.1` format. To perform a rolling deploy of a Rails 7.1
|
|
520
|
-
upgrade, wherein servers that have not yet been upgraded must be able to
|
|
521
|
-
read caches from upgraded servers, leave the cache format unchanged on the
|
|
522
|
-
first deploy, then enable the `7.1` cache format on a subsequent deploy.
|
|
523
|
-
|
|
524
|
-
*Jonathan Hefner*
|
|
525
|
-
|
|
526
|
-
* Active Support cache stores can now use a preconfigured serializer based on
|
|
527
|
-
`ActiveSupport::MessagePack` via the `:serializer` option:
|
|
528
|
-
|
|
529
|
-
```ruby
|
|
530
|
-
config.cache_store = :redis_cache_store, { serializer: :message_pack }
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
The `:message_pack` serializer can reduce cache entry sizes and improve
|
|
534
|
-
performance, but requires the [`msgpack` gem](https://rubygems.org/gems/msgpack)
|
|
535
|
-
(>= 1.7.0).
|
|
536
|
-
|
|
537
|
-
The `:message_pack` serializer can read cache entries written by the default
|
|
538
|
-
serializer, and the default serializer can now read entries written by the
|
|
539
|
-
`:message_pack` serializer. These behaviors make it easy to migrate between
|
|
540
|
-
serializer without invalidating the entire cache.
|
|
541
|
-
|
|
542
|
-
*Jonathan Hefner*
|
|
543
|
-
|
|
544
|
-
* `Object#deep_dup` no longer duplicate named classes and modules.
|
|
545
|
-
|
|
546
|
-
Before:
|
|
207
|
+
The Event Reporter provides a unified interface for producing structured events in Rails
|
|
208
|
+
applications:
|
|
547
209
|
|
|
548
210
|
```ruby
|
|
549
|
-
|
|
550
|
-
hash.deep_dup # => {:class=>#<Class:0x00000001063ffc80>, :module=>#<Module:0x00000001063ffa00>}
|
|
211
|
+
Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
|
|
551
212
|
```
|
|
552
213
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
```ruby
|
|
556
|
-
hash = { class: Object, module: Kernel }
|
|
557
|
-
hash.deep_dup # => {:class=>Object, :module=>Kernel}
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
*Jean Boussier*
|
|
561
|
-
|
|
562
|
-
* Consistently raise an `ArgumentError` if the `ActiveSupport::Cache` key is blank.
|
|
563
|
-
|
|
564
|
-
*Joshua Young*
|
|
565
|
-
|
|
566
|
-
* Deprecate usage of the singleton `ActiveSupport::Deprecation`.
|
|
567
|
-
|
|
568
|
-
All usage of `ActiveSupport::Deprecation` as a singleton is deprecated, the most common one being
|
|
569
|
-
`ActiveSupport::Deprecation.warn`. Gem authors should now create their own deprecator (`ActiveSupport::Deprecation`
|
|
570
|
-
object), and use it to emit deprecation warnings.
|
|
571
|
-
|
|
572
|
-
Calling any of the following without specifying a deprecator argument is also deprecated:
|
|
573
|
-
* Module.deprecate
|
|
574
|
-
* deprecate_constant
|
|
575
|
-
* DeprecatedObjectProxy
|
|
576
|
-
* DeprecatedInstanceVariableProxy
|
|
577
|
-
* DeprecatedConstantProxy
|
|
578
|
-
* deprecation-related test assertions
|
|
579
|
-
|
|
580
|
-
Use of `ActiveSupport::Deprecation.silence` and configuration methods like `behavior=`, `disallowed_behavior=`,
|
|
581
|
-
`disallowed_warnings=` should now be aimed at the [application's deprecators](https://api.rubyonrails.org/classes/Rails/Application.html#method-i-deprecators).
|
|
214
|
+
It supports adding tags to events:
|
|
582
215
|
|
|
583
216
|
```ruby
|
|
584
|
-
Rails.
|
|
585
|
-
#
|
|
217
|
+
Rails.event.tagged("graphql") do
|
|
218
|
+
# Event includes tags: { graphql: true }
|
|
219
|
+
Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
|
|
586
220
|
end
|
|
587
221
|
```
|
|
588
222
|
|
|
589
|
-
|
|
590
|
-
way the deprecation related configuration options will apply to it as well, e.g.
|
|
591
|
-
`config.active_support.report_deprecations` set to `false` in the production environment will also disable your
|
|
592
|
-
deprecator.
|
|
593
|
-
|
|
223
|
+
As well as context:
|
|
594
224
|
```ruby
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
end
|
|
225
|
+
# All events will contain context: {request_id: "abc123", shop_id: 456}
|
|
226
|
+
Rails.event.set_context(request_id: "abc123", shop_id: 456)
|
|
598
227
|
```
|
|
599
228
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
229
|
+
Events are emitted to subscribers. Applications register subscribers to
|
|
230
|
+
control how events are serialized and emitted. Subscribers must implement
|
|
231
|
+
an `#emit` method, which receives the event hash:
|
|
603
232
|
|
|
604
233
|
```ruby
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
234
|
+
class LogSubscriber
|
|
235
|
+
def emit(event)
|
|
236
|
+
payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ")
|
|
237
|
+
source_location = event[:source_location]
|
|
238
|
+
log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}"
|
|
239
|
+
Rails.logger.info(log)
|
|
240
|
+
end
|
|
608
241
|
end
|
|
609
|
-
client.timeout # => 5
|
|
610
242
|
```
|
|
611
243
|
|
|
612
|
-
*
|
|
613
|
-
|
|
614
|
-
* Remove deprecated support to generate incorrect RFC 4122 UUIDs when providing a namespace ID that is not one of the
|
|
615
|
-
constants defined on `Digest::UUID`.
|
|
616
|
-
|
|
617
|
-
*Rafael Mendonça França*
|
|
618
|
-
|
|
619
|
-
* Deprecate `config.active_support.use_rfc4122_namespaced_uuids`.
|
|
620
|
-
|
|
621
|
-
*Rafael Mendonça França*
|
|
622
|
-
|
|
623
|
-
* Remove implicit conversion of objects into `String` by `ActiveSupport::SafeBuffer`.
|
|
624
|
-
|
|
625
|
-
*Rafael Mendonça França*
|
|
626
|
-
|
|
627
|
-
* Remove deprecated `active_support/core_ext/range/include_time_with_zone` file.
|
|
628
|
-
|
|
629
|
-
*Rafael Mendonça França*
|
|
630
|
-
|
|
631
|
-
* Deprecate `config.active_support.remove_deprecated_time_with_zone_name`.
|
|
632
|
-
|
|
633
|
-
*Rafael Mendonça França*
|
|
634
|
-
|
|
635
|
-
* Remove deprecated override of `ActiveSupport::TimeWithZone.name`.
|
|
636
|
-
|
|
637
|
-
*Rafael Mendonça França*
|
|
638
|
-
|
|
639
|
-
* Deprecate `config.active_support.disable_to_s_conversion`.
|
|
640
|
-
|
|
641
|
-
*Rafael Mendonça França*
|
|
642
|
-
|
|
643
|
-
* Remove deprecated option to passing a format to `#to_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
|
|
644
|
-
`BigDecimal`, `Float` and, `Integer`.
|
|
645
|
-
|
|
646
|
-
*Rafael Mendonça França*
|
|
647
|
-
|
|
648
|
-
* Remove deprecated `ActiveSupport::PerThreadRegistry`.
|
|
649
|
-
|
|
650
|
-
*Rafael Mendonça França*
|
|
651
|
-
|
|
652
|
-
* Remove deprecated override of `Enumerable#sum`.
|
|
653
|
-
|
|
654
|
-
*Rafael Mendonça França*
|
|
655
|
-
|
|
656
|
-
* Deprecated initializing a `ActiveSupport::Cache::MemCacheStore` with an instance of `Dalli::Client`.
|
|
657
|
-
|
|
658
|
-
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.
|
|
659
|
-
|
|
660
|
-
*aledustet*
|
|
661
|
-
|
|
662
|
-
* Stub `Time.new()` in `TimeHelpers#travel_to`
|
|
663
|
-
|
|
664
|
-
```ruby
|
|
665
|
-
travel_to Time.new(2004, 11, 24) do
|
|
666
|
-
# Inside the `travel_to` block `Time.new` is stubbed
|
|
667
|
-
assert_equal 2004, Time.new.year
|
|
668
|
-
end
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
*fatkodima*
|
|
672
|
-
|
|
673
|
-
* Raise `ActiveSupport::MessageEncryptor::InvalidMessage` from
|
|
674
|
-
`ActiveSupport::MessageEncryptor#decrypt_and_verify` regardless of cipher.
|
|
675
|
-
Previously, when a `MessageEncryptor` was using a non-AEAD cipher such as
|
|
676
|
-
AES-256-CBC, a corrupt or tampered message would raise
|
|
677
|
-
`ActiveSupport::MessageVerifier::InvalidSignature`. Now, all ciphers raise
|
|
678
|
-
the same error:
|
|
679
|
-
|
|
680
|
-
```ruby
|
|
681
|
-
encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-gcm")
|
|
682
|
-
message = encryptor.encrypt_and_sign("message")
|
|
683
|
-
encryptor.decrypt_and_verify(message.next)
|
|
684
|
-
# => raises ActiveSupport::MessageEncryptor::InvalidMessage
|
|
685
|
-
|
|
686
|
-
encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-cbc")
|
|
687
|
-
message = encryptor.encrypt_and_sign("message")
|
|
688
|
-
encryptor.decrypt_and_verify(message.next)
|
|
689
|
-
# BEFORE:
|
|
690
|
-
# => raises ActiveSupport::MessageVerifier::InvalidSignature
|
|
691
|
-
# AFTER:
|
|
692
|
-
# => raises ActiveSupport::MessageEncryptor::InvalidMessage
|
|
693
|
-
```
|
|
694
|
-
|
|
695
|
-
*Jonathan Hefner*
|
|
696
|
-
|
|
697
|
-
* Support `nil` original values when using `ActiveSupport::MessageVerifier#verify`.
|
|
698
|
-
Previously, `MessageVerifier#verify` did not work with `nil` original
|
|
699
|
-
values, though both `MessageVerifier#verified` and
|
|
700
|
-
`MessageEncryptor#decrypt_and_verify` do:
|
|
244
|
+
*Adrianna Chang*
|
|
701
245
|
|
|
702
|
-
|
|
703
|
-
encryptor = ActiveSupport::MessageEncryptor.new(secret)
|
|
704
|
-
message = encryptor.encrypt_and_sign(nil)
|
|
246
|
+
* Make `ActiveSupport::Logger` `#freeze`-friendly.
|
|
705
247
|
|
|
706
|
-
|
|
707
|
-
# => nil
|
|
708
|
-
|
|
709
|
-
verifier = ActiveSupport::MessageVerifier.new(secret)
|
|
710
|
-
message = verifier.generate(nil)
|
|
711
|
-
|
|
712
|
-
verifier.verified(message)
|
|
713
|
-
# => nil
|
|
714
|
-
|
|
715
|
-
verifier.verify(message)
|
|
716
|
-
# BEFORE:
|
|
717
|
-
# => raises ActiveSupport::MessageVerifier::InvalidSignature
|
|
718
|
-
# AFTER:
|
|
719
|
-
# => nil
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
*Jonathan Hefner*
|
|
723
|
-
|
|
724
|
-
* Maintain `html_safe?` on html_safe strings when sliced with `slice`, `slice!`, or `chr` method.
|
|
248
|
+
*Joshua Young*
|
|
725
249
|
|
|
726
|
-
|
|
727
|
-
with `[]` method. Now, `slice`, `slice!`, and `chr` methods will maintain `html_safe?` like `[]` method.
|
|
250
|
+
* Make `ActiveSupport::Gzip.compress` deterministic based on input.
|
|
728
251
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
# maintain html_safe? after the slice!
|
|
734
|
-
string.html_safe? # => true
|
|
735
|
-
string.chr.html_safe? # => true
|
|
736
|
-
```
|
|
252
|
+
`ActiveSupport::Gzip.compress` used to include a timestamp in the output,
|
|
253
|
+
causing consecutive calls with the same input data to have different output
|
|
254
|
+
if called during different seconds. It now always sets the timestamp to `0`
|
|
255
|
+
so that the output is identical for any given input.
|
|
737
256
|
|
|
738
|
-
*
|
|
257
|
+
*Rob Brackett*
|
|
739
258
|
|
|
740
|
-
*
|
|
259
|
+
* Given an array of `Thread::Backtrace::Location` objects, the new method
|
|
260
|
+
`ActiveSupport::BacktraceCleaner#clean_locations` returns an array with the
|
|
261
|
+
clean ones:
|
|
741
262
|
|
|
742
263
|
```ruby
|
|
743
|
-
|
|
744
|
-
assert_not Date.today.in?(Date.tomorrow..)
|
|
264
|
+
clean_locations = backtrace_cleaner.clean_locations(caller_locations)
|
|
745
265
|
```
|
|
746
266
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
Previously it would only raise when called in a view or controller. Now it will raise
|
|
752
|
-
anytime `I18n.t` is provided an unrecognised key.
|
|
753
|
-
|
|
754
|
-
If you do not want this behaviour, you can customise the i18n exception handler. See the
|
|
755
|
-
upgrading guide or i18n guide for more information.
|
|
756
|
-
|
|
757
|
-
*Alex Ghiculescu*
|
|
758
|
-
|
|
759
|
-
* `ActiveSupport::CurrentAttributes` now raises if a restricted attribute name is used.
|
|
760
|
-
|
|
761
|
-
Attributes such as `set` and `reset` cannot be used as they clash with the
|
|
762
|
-
`CurrentAttributes` public API.
|
|
267
|
+
Filters and silencers receive strings as usual. However, the `path`
|
|
268
|
+
attributes of the locations in the returned array are the original,
|
|
269
|
+
unfiltered ones, since locations are immutable.
|
|
763
270
|
|
|
764
|
-
*
|
|
765
|
-
|
|
766
|
-
* `HashWithIndifferentAccess#transform_keys` now takes a Hash argument, just
|
|
767
|
-
as Ruby's `Hash#transform_keys` does.
|
|
271
|
+
*Xavier Noria*
|
|
768
272
|
|
|
769
|
-
|
|
273
|
+
* Improve `CurrentAttributes` and `ExecutionContext` state managment in test cases.
|
|
770
274
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
be defined before declaring the delegation.
|
|
275
|
+
Previously these two global state would be entirely cleared out whenever calling
|
|
276
|
+
into code that is wrapped by the Rails executor, typically Action Controller or
|
|
277
|
+
Active Job helpers:
|
|
775
278
|
|
|
776
279
|
```ruby
|
|
777
|
-
#
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
end
|
|
782
|
-
|
|
783
|
-
class C
|
|
784
|
-
# This works but silently falls back to old behavior because
|
|
785
|
-
# `delegate` cannot find the definition of `x`
|
|
786
|
-
delegate :x, to: :class
|
|
787
|
-
def self.x() end
|
|
280
|
+
test "#index works" do
|
|
281
|
+
CurrentUser.id = 42
|
|
282
|
+
get :index
|
|
283
|
+
CurrentUser.id == nil
|
|
788
284
|
end
|
|
789
285
|
```
|
|
790
286
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
* `assert_difference` message now includes what changed.
|
|
794
|
-
|
|
795
|
-
This makes it easier to debug non-obvious failures.
|
|
287
|
+
Now re-entering the executor properly save and restore that state.
|
|
796
288
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
```
|
|
800
|
-
"User.count" didn't change by 32.
|
|
801
|
-
Expected: 1611
|
|
802
|
-
Actual: 1579
|
|
803
|
-
```
|
|
289
|
+
*Jean Boussier*
|
|
804
290
|
|
|
805
|
-
|
|
291
|
+
* The new method `ActiveSupport::BacktraceCleaner#first_clean_location`
|
|
292
|
+
returns the first clean location of the caller's call stack, or `nil`.
|
|
293
|
+
Locations are `Thread::Backtrace::Location` objects. Useful when you want to
|
|
294
|
+
report the application-level location where something happened as an object.
|
|
806
295
|
|
|
807
|
-
|
|
808
|
-
"User.count" didn't change by 32, but by 0.
|
|
809
|
-
Expected: 1611
|
|
810
|
-
Actual: 1579
|
|
811
|
-
```
|
|
296
|
+
*Xavier Noria*
|
|
812
297
|
|
|
813
|
-
|
|
298
|
+
* FileUpdateChecker and EventedFileUpdateChecker ignore changes in Gem.path now.
|
|
814
299
|
|
|
815
|
-
*
|
|
300
|
+
*Ermolaev Andrey*, *zzak*
|
|
816
301
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
end
|
|
822
|
-
assert_match(/incorrect param/i, error.message)
|
|
823
|
-
```
|
|
302
|
+
* The new method `ActiveSupport::BacktraceCleaner#first_clean_frame` returns
|
|
303
|
+
the first clean frame of the caller's backtrace, or `nil`. Useful when you
|
|
304
|
+
want to report the application-level frame where something happened as a
|
|
305
|
+
string.
|
|
824
306
|
|
|
825
|
-
|
|
826
|
-
```ruby
|
|
827
|
-
assert_raises(ArgumentError, match: /incorrect param/i) do
|
|
828
|
-
perform_service(param: 'exception')
|
|
829
|
-
end
|
|
830
|
-
```
|
|
307
|
+
*Xavier Noria*
|
|
831
308
|
|
|
832
|
-
|
|
309
|
+
* Always clear `CurrentAttributes` instances.
|
|
833
310
|
|
|
834
|
-
|
|
311
|
+
Previously `CurrentAttributes` instance would be reset at the end of requests.
|
|
312
|
+
Meaning its attributes would be re-initialized.
|
|
835
313
|
|
|
836
|
-
|
|
314
|
+
This is problematic because it assume these objects don't hold any state
|
|
315
|
+
other than their declared attribute, which isn't always the case, and
|
|
316
|
+
can lead to state leak across request.
|
|
837
317
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
truncating the destination time with `change(usec: 0)`.
|
|
318
|
+
Now `CurrentAttributes` instances are abandoned at the end of a request,
|
|
319
|
+
and a new instance is created at the start of the next request.
|
|
841
320
|
|
|
842
|
-
*
|
|
321
|
+
*Jean Boussier*, *Janko Marohnić*
|
|
843
322
|
|
|
844
|
-
* `
|
|
323
|
+
* Add public API for `before_fork_hook` in parallel testing.
|
|
845
324
|
|
|
846
|
-
|
|
325
|
+
Introduces a public API for calling the before fork hooks implemented by parallel testing.
|
|
847
326
|
|
|
848
327
|
```ruby
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
resets :clear_time_zone
|
|
328
|
+
parallelize_before_fork do
|
|
329
|
+
# perform an action before test processes are forked
|
|
852
330
|
end
|
|
853
331
|
```
|
|
854
332
|
|
|
855
|
-
*
|
|
856
|
-
|
|
857
|
-
* Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
|
|
858
|
-
|
|
859
|
-
Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
|
|
860
|
-
process closed the read end, wrote to it, and then terminated (which
|
|
861
|
-
presumably closed the file descriptors on its end). The parent process
|
|
862
|
-
closed the write end, read from it, and returned, never closing the read
|
|
863
|
-
end.
|
|
864
|
-
|
|
865
|
-
This resulted in an accumulation of open file descriptors, which could
|
|
866
|
-
cause errors if the limit is reached.
|
|
333
|
+
*Eileen M. Uchitelle*
|
|
867
334
|
|
|
868
|
-
|
|
335
|
+
* Implement ability to skip creating parallel testing databases.
|
|
869
336
|
|
|
870
|
-
|
|
871
|
-
|
|
337
|
+
With parallel testing, Rails will create a database per process. If this isn't
|
|
338
|
+
desirable or you would like to implement databases handling on your own, you can
|
|
339
|
+
now turn off this default behavior.
|
|
872
340
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
always be chosen for local times:
|
|
341
|
+
To skip creating a database per process, you can change it via the
|
|
342
|
+
`parallelize` method:
|
|
876
343
|
|
|
877
344
|
```ruby
|
|
878
|
-
|
|
879
|
-
ENV["TZ"] = "US/Eastern"
|
|
880
|
-
|
|
881
|
-
time = Time.local(2021, 11, 07, 00, 59, 59) + 1
|
|
882
|
-
# => 2021-11-07 01:00:00 -0400
|
|
883
|
-
time.change(day: 07)
|
|
884
|
-
# => 2021-11-07 01:00:00 -0500
|
|
885
|
-
time.advance(seconds: 0)
|
|
886
|
-
# => 2021-11-07 01:00:00 -0500
|
|
887
|
-
|
|
888
|
-
time = Time.local(2021, 11, 06, 01, 00, 00)
|
|
889
|
-
# => 2021-11-06 01:00:00 -0400
|
|
890
|
-
time.change(day: 07)
|
|
891
|
-
# => 2021-11-07 01:00:00 -0500
|
|
892
|
-
time.advance(days: 1)
|
|
893
|
-
# => 2021-11-07 01:00:00 -0500
|
|
345
|
+
parallelize(workers: 10, parallelize_databases: false)
|
|
894
346
|
```
|
|
895
347
|
|
|
896
|
-
|
|
897
|
-
object:
|
|
348
|
+
or via the application configuration:
|
|
898
349
|
|
|
899
350
|
```ruby
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
|
|
903
|
-
# => 2021-11-07 01:00:00 -0500
|
|
904
|
-
time.change(day: 07)
|
|
905
|
-
# => 2021-11-07 01:00:00 -0400
|
|
906
|
-
time.advance(seconds: 0)
|
|
907
|
-
# => 2021-11-07 01:00:00 -0400
|
|
908
|
-
|
|
909
|
-
time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
|
|
910
|
-
# => 2021-11-08 01:00:00 -0500
|
|
911
|
-
time.change(day: 07)
|
|
912
|
-
# => 2021-11-07 01:00:00 -0400
|
|
913
|
-
time.advance(days: -1)
|
|
914
|
-
# => 2021-11-07 01:00:00 -0400
|
|
351
|
+
config.active_support.parallelize_databases = false
|
|
915
352
|
```
|
|
916
353
|
|
|
917
|
-
|
|
918
|
-
the original time's offset when possible:
|
|
919
|
-
|
|
920
|
-
```ruby
|
|
921
|
-
ENV["TZ"] = "US/Eastern"
|
|
922
|
-
|
|
923
|
-
time = Time.local(2021, 11, 07, 00, 59, 59) + 1
|
|
924
|
-
# => 2021-11-07 01:00:00 -0400
|
|
925
|
-
time.change(day: 07)
|
|
926
|
-
# => 2021-11-07 01:00:00 -0400
|
|
927
|
-
time.advance(seconds: 0)
|
|
928
|
-
# => 2021-11-07 01:00:00 -0400
|
|
929
|
-
|
|
930
|
-
time = Time.local(2021, 11, 06, 01, 00, 00)
|
|
931
|
-
# => 2021-11-06 01:00:00 -0400
|
|
932
|
-
time.change(day: 07)
|
|
933
|
-
# => 2021-11-07 01:00:00 -0400
|
|
934
|
-
time.advance(days: 1)
|
|
935
|
-
# => 2021-11-07 01:00:00 -0400
|
|
936
|
-
|
|
937
|
-
Time.zone = "US/Eastern"
|
|
938
|
-
|
|
939
|
-
time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
|
|
940
|
-
# => 2021-11-07 01:00:00 -0500
|
|
941
|
-
time.change(day: 07)
|
|
942
|
-
# => 2021-11-07 01:00:00 -0500
|
|
943
|
-
time.advance(seconds: 0)
|
|
944
|
-
# => 2021-11-07 01:00:00 -0500
|
|
945
|
-
|
|
946
|
-
time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
|
|
947
|
-
# => 2021-11-08 01:00:00 -0500
|
|
948
|
-
time.change(day: 07)
|
|
949
|
-
# => 2021-11-07 01:00:00 -0500
|
|
950
|
-
time.advance(days: -1)
|
|
951
|
-
# => 2021-11-07 01:00:00 -0500
|
|
952
|
-
```
|
|
354
|
+
*Eileen M. Uchitelle*
|
|
953
355
|
|
|
954
|
-
|
|
356
|
+
* Allow to configure maximum cache key sizes
|
|
955
357
|
|
|
956
|
-
|
|
358
|
+
When the key exceeds the configured limit (250 bytes by default), it will be truncated and
|
|
359
|
+
the digest of the rest of the key appended to it.
|
|
957
360
|
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
*Jean Boussier*
|
|
961
|
-
|
|
962
|
-
* `Rails.error.handle` and `Rails.error.record` filter now by multiple error classes.
|
|
361
|
+
Note that previously `ActiveSupport::Cache::RedisCacheStore` allowed up to 1kb cache keys before
|
|
362
|
+
truncation, which is now reduced to 250 bytes.
|
|
963
363
|
|
|
964
364
|
```ruby
|
|
965
|
-
|
|
966
|
-
1 + '1' # raises TypeError
|
|
967
|
-
end
|
|
968
|
-
1 + 1 # TypeErrors are not IOErrors or ArgumentError, so this will *not* be handled
|
|
365
|
+
config.cache_store = :redis_cache_store, { max_key_size: 64 }
|
|
969
366
|
```
|
|
970
367
|
|
|
971
|
-
*
|
|
972
|
-
|
|
973
|
-
* `Class#subclasses` and `Class#descendants` now automatically filter reloaded classes.
|
|
974
|
-
|
|
975
|
-
Previously they could return old implementations of reloadable classes that have been
|
|
976
|
-
dereferenced but not yet garbage collected.
|
|
977
|
-
|
|
978
|
-
They now automatically filter such classes like `DescendantTracker#subclasses` and
|
|
979
|
-
`DescendantTracker#descendants`.
|
|
368
|
+
*fatkodima*
|
|
980
369
|
|
|
981
|
-
|
|
370
|
+
* Use `UNLINK` command instead of `DEL` in `ActiveSupport::Cache::RedisCacheStore` for non-blocking deletion.
|
|
982
371
|
|
|
983
|
-
*
|
|
372
|
+
*Aron Roh*
|
|
984
373
|
|
|
985
|
-
|
|
986
|
-
before letting it bubble up.
|
|
374
|
+
* Add `Cache#read_counter` and `Cache#write_counter`
|
|
987
375
|
|
|
988
|
-
|
|
376
|
+
```ruby
|
|
377
|
+
Rails.cache.write_counter("foo", 1)
|
|
378
|
+
Rails.cache.read_counter("foo") # => 1
|
|
379
|
+
Rails.cache.increment("foo")
|
|
380
|
+
Rails.cache.read_counter("foo") # => 2
|
|
381
|
+
```
|
|
989
382
|
|
|
990
|
-
*
|
|
383
|
+
*Alex Ghiculescu*
|
|
991
384
|
|
|
992
|
-
*
|
|
385
|
+
* Introduce ActiveSupport::Testing::ErrorReporterAssertions#capture_error_reports
|
|
993
386
|
|
|
994
|
-
|
|
387
|
+
Captures all reported errors from within the block that match the given
|
|
388
|
+
error class.
|
|
995
389
|
|
|
996
390
|
```ruby
|
|
997
|
-
|
|
998
|
-
|
|
391
|
+
reports = capture_error_reports(IOError) do
|
|
392
|
+
Rails.error.report(IOError.new("Oops"))
|
|
393
|
+
Rails.error.report(IOError.new("Oh no"))
|
|
394
|
+
Rails.error.report(StandardError.new)
|
|
999
395
|
end
|
|
1000
|
-
|
|
1001
|
-
assert_equal
|
|
1002
|
-
assert_equal
|
|
1003
|
-
|
|
396
|
+
|
|
397
|
+
assert_equal 2, reports.size
|
|
398
|
+
assert_equal "Oops", reports.first.error.message
|
|
399
|
+
assert_equal "Oh no", reports.last.error.message
|
|
1004
400
|
```
|
|
1005
401
|
|
|
1006
|
-
*
|
|
402
|
+
*Andrew Novoselac*
|
|
1007
403
|
|
|
1008
|
-
*
|
|
1009
|
-
deprecator instance as an argument. This makes it easier for such callbacks
|
|
1010
|
-
to change their behavior based on the deprecator's state. For example,
|
|
1011
|
-
based on the deprecator's `debug` flag.
|
|
404
|
+
* Introduce ActiveSupport::ErrorReporter#add_middleware
|
|
1012
405
|
|
|
1013
|
-
|
|
1014
|
-
the
|
|
406
|
+
When reporting an error, the error context middleware will be called with the reported error
|
|
407
|
+
and base execution context. The stack may mutate the context hash. The mutated context will
|
|
408
|
+
then be passed to error subscribers. Middleware receives the same parameters as `ErrorReporter#report`.
|
|
1015
409
|
|
|
1016
|
-
*
|
|
1017
|
-
* `->(*args) { ... }`
|
|
1018
|
-
* `->(message, *other_args) { ... }`
|
|
410
|
+
*Andrew Novoselac*, *Sam Schmidt*
|
|
1019
411
|
|
|
1020
|
-
|
|
1021
|
-
the same as before:
|
|
412
|
+
* Change execution wrapping to report all exceptions, including `Exception`.
|
|
1022
413
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
* `->(message, callstack, *deprecation_details) { ... }`
|
|
414
|
+
If a more serious error like `SystemStackError` or `NoMemoryError` happens,
|
|
415
|
+
the error reporter should be able to report these kinds of exceptions.
|
|
1026
416
|
|
|
1027
|
-
*
|
|
417
|
+
*Gannon McGibbon*
|
|
1028
418
|
|
|
1029
|
-
* `ActiveSupport::
|
|
1030
|
-
|
|
419
|
+
* `ActiveSupport::Testing::Parallelization.before_fork_hook` allows declaration of callbacks that
|
|
420
|
+
are invoked immediately before forking test workers.
|
|
1031
421
|
|
|
1032
|
-
|
|
1033
|
-
configured with their own disallowed warnings, and the global
|
|
1034
|
-
`ActiveSupport::Deprecation.disallowed_warnings` now only affects the global
|
|
1035
|
-
`ActiveSupport::Deprecation.warn`.
|
|
422
|
+
*Mike Dalessio*
|
|
1036
423
|
|
|
1037
|
-
|
|
424
|
+
* Allow the `#freeze_time` testing helper to accept a date or time argument.
|
|
1038
425
|
|
|
1039
426
|
```ruby
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
|
|
1045
|
-
ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
|
|
1046
|
-
deprecator.warn("foo") # => raise ActiveSupport::DeprecationException
|
|
1047
|
-
deprecator.warn("bar") # => print "DEPRECATION WARNING: bar"
|
|
427
|
+
Time.current # => Sun, 09 Jul 2024 15:34:49 EST -05:00
|
|
428
|
+
freeze_time Time.current + 1.day
|
|
429
|
+
sleep 1
|
|
430
|
+
Time.current # => Mon, 10 Jul 2024 15:34:49 EST -05:00
|
|
1048
431
|
```
|
|
1049
432
|
|
|
1050
|
-
|
|
433
|
+
*Joshua Young*
|
|
434
|
+
|
|
435
|
+
* `ActiveSupport::JSON` now accepts options
|
|
1051
436
|
|
|
437
|
+
It is now possible to pass options to `ActiveSupport::JSON`:
|
|
1052
438
|
```ruby
|
|
1053
|
-
ActiveSupport::
|
|
1054
|
-
deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
|
|
1055
|
-
deprecator.disallowed_warnings = ["bar"]
|
|
1056
|
-
|
|
1057
|
-
ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
|
|
1058
|
-
ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
|
|
1059
|
-
deprecator.warn("foo") # => print "DEPRECATION WARNING: foo"
|
|
1060
|
-
deprecator.warn("bar") # => raise ActiveSupport::DeprecationException
|
|
439
|
+
ActiveSupport::JSON.decode('{"key": "value"}', symbolize_names: true) # => { key: "value" }
|
|
1061
440
|
```
|
|
1062
441
|
|
|
1063
|
-
|
|
1064
|
-
and `ActiveSupport::Deprecation.disallowed_warnings` have been deprecated.
|
|
1065
|
-
|
|
1066
|
-
*Jonathan Hefner*
|
|
442
|
+
*matthaigh27*
|
|
1067
443
|
|
|
1068
|
-
*
|
|
444
|
+
* `ActiveSupport::Testing::NotificationAssertions`'s `assert_notification` now matches against payload subsets by default.
|
|
1069
445
|
|
|
1070
|
-
Previously
|
|
1071
|
-
This allows for bold, italic, and underline options to be specified
|
|
1072
|
-
for colored logs.
|
|
446
|
+
Previously the following assertion would fail due to excess key vals in the notification payload. Now with payload subset matching, it will pass.
|
|
1073
447
|
|
|
1074
448
|
```ruby
|
|
1075
|
-
|
|
449
|
+
assert_notification("post.submitted", title: "Cool Post") do
|
|
450
|
+
ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: "Cool Body")
|
|
451
|
+
end
|
|
1076
452
|
```
|
|
1077
453
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
* Add `String#downcase_first` method.
|
|
454
|
+
Additionally, you can now persist a matched notification for more customized assertions.
|
|
1081
455
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
* `thread_mattr_accessor` will call `.dup.freeze` on non-frozen default values.
|
|
1087
|
-
|
|
1088
|
-
This provides a basic level of protection against different threads trying
|
|
1089
|
-
to mutate a shared default object.
|
|
1090
|
-
|
|
1091
|
-
*Jonathan Hefner*
|
|
1092
|
-
|
|
1093
|
-
* Add `raise_on_invalid_cache_expiration_time` config to `ActiveSupport::Cache::Store`
|
|
1094
|
-
|
|
1095
|
-
Specifies if an `ArgumentError` should be raised if `Rails.cache` `fetch` or
|
|
1096
|
-
`write` are given an invalid `expires_at` or `expires_in` time.
|
|
1097
|
-
|
|
1098
|
-
Options are `true`, and `false`. If `false`, the exception will be reported
|
|
1099
|
-
as `handled` and logged instead. Defaults to `true` if `config.load_defaults >= 7.1`.
|
|
1100
|
-
|
|
1101
|
-
*Trevor Turk*
|
|
1102
|
-
|
|
1103
|
-
* `ActiveSupport::Cache::Store#fetch` now passes an options accessor to the block.
|
|
1104
|
-
|
|
1105
|
-
It makes possible to override cache options:
|
|
1106
|
-
|
|
1107
|
-
Rails.cache.fetch("3rd-party-token") do |name, options|
|
|
1108
|
-
token = fetch_token_from_remote
|
|
1109
|
-
# set cache's TTL to match token's TTL
|
|
1110
|
-
options.expires_in = token.expires_in
|
|
1111
|
-
token
|
|
1112
|
-
end
|
|
1113
|
-
|
|
1114
|
-
*Andrii Gladkyi*, *Jean Boussier*
|
|
1115
|
-
|
|
1116
|
-
* `default` option of `thread_mattr_accessor` now applies through inheritance and
|
|
1117
|
-
also across new threads.
|
|
456
|
+
```ruby
|
|
457
|
+
notification = assert_notification("post.submitted", title: "Cool Post") do
|
|
458
|
+
ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: Body.new("Cool Body"))
|
|
459
|
+
end
|
|
1118
460
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
descendants and in other threads.
|
|
461
|
+
assert_instance_of(Body, notification.payload[:body])
|
|
462
|
+
```
|
|
1122
463
|
|
|
1123
|
-
|
|
464
|
+
*Nicholas La Roux*
|
|
1124
465
|
|
|
1125
|
-
|
|
466
|
+
* Deprecate `String#mb_chars` and `ActiveSupport::Multibyte::Chars`.
|
|
1126
467
|
|
|
1127
|
-
|
|
468
|
+
These APIs are a relic of the Ruby 1.8 days when Ruby strings weren't encoding
|
|
469
|
+
aware. There is no legitimate reasons to need these APIs today.
|
|
1128
470
|
|
|
1129
471
|
*Jean Boussier*
|
|
1130
472
|
|
|
1131
|
-
*
|
|
1132
|
-
|
|
1133
|
-
*Daniel Alfaro*
|
|
1134
|
-
|
|
1135
|
-
* Add `quarter` method to date/time
|
|
473
|
+
* Deprecate `ActiveSupport::Configurable`
|
|
1136
474
|
|
|
1137
|
-
*
|
|
475
|
+
*Sean Doyle*
|
|
1138
476
|
|
|
1139
|
-
*
|
|
477
|
+
* `nil.to_query("key")` now returns `key`.
|
|
1140
478
|
|
|
1141
|
-
`
|
|
1142
|
-
that responds to `call`, but in fact its internal implementation assumed that
|
|
1143
|
-
this object could respond to `arity`, so it was restricted to only `Proc` objects.
|
|
479
|
+
Previously it would return `key=`, preventing round tripping with `Rack::Utils.parse_nested_query`.
|
|
1144
480
|
|
|
1145
|
-
|
|
481
|
+
*Erol Fornoles*
|
|
1146
482
|
|
|
1147
|
-
|
|
483
|
+
* Avoid wrapping redis in a `ConnectionPool` when using `ActiveSupport::Cache::RedisCacheStore` if the `:redis`
|
|
484
|
+
option is already a `ConnectionPool`.
|
|
1148
485
|
|
|
1149
|
-
*
|
|
1150
|
-
|
|
1151
|
-
The `MessageEncryptor` constructor now accepts a `:url_safe` option, similar
|
|
1152
|
-
to the `MessageVerifier` constructor. When enabled, this option ensures
|
|
1153
|
-
that messages use a URL-safe encoding.
|
|
486
|
+
*Joshua Young*
|
|
1154
487
|
|
|
1155
|
-
|
|
488
|
+
* Alter `ERB::Util.tokenize` to return :PLAIN token with full input string when string doesn't contain ERB tags.
|
|
1156
489
|
|
|
1157
|
-
*
|
|
490
|
+
*Martin Emde*
|
|
1158
491
|
|
|
1159
|
-
|
|
1160
|
-
It can generate URL-safe strings by passing `url_safe: true`.
|
|
492
|
+
* Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceded by multibyte characters.
|
|
1161
493
|
|
|
1162
|
-
|
|
1163
|
-
verifier = ActiveSupport::MessageVerifier.new(url_safe: true)
|
|
1164
|
-
message = verifier.generate(data) # => URL-safe string
|
|
1165
|
-
```
|
|
494
|
+
*Martin Emde*
|
|
1166
495
|
|
|
1167
|
-
|
|
496
|
+
* Add `ActiveSupport::Testing::NotificationAssertions` module to help with testing `ActiveSupport::Notifications`.
|
|
1168
497
|
|
|
1169
|
-
*
|
|
498
|
+
*Nicholas La Roux*, *Yishu See*, *Sean Doyle*
|
|
1170
499
|
|
|
1171
|
-
*
|
|
500
|
+
* `ActiveSupport::CurrentAttributes#attributes` now will return a new hash object on each call.
|
|
1172
501
|
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
```ruby
|
|
1176
|
-
config.cache_store = :mem_cache_store, "cache.example.com", pool: false
|
|
1177
|
-
```
|
|
1178
|
-
|
|
1179
|
-
*fatkodima*
|
|
1180
|
-
|
|
1181
|
-
* Add `force:` support to `ActiveSupport::Cache::Store#fetch_multi`.
|
|
502
|
+
Previously, the same hash object was returned each time that method was called.
|
|
1182
503
|
|
|
1183
504
|
*fatkodima*
|
|
1184
505
|
|
|
1185
|
-
*
|
|
506
|
+
* `ActiveSupport::JSON.encode` supports CIDR notation.
|
|
1186
507
|
|
|
1187
|
-
|
|
508
|
+
Previously:
|
|
1188
509
|
|
|
1189
510
|
```ruby
|
|
1190
|
-
|
|
511
|
+
ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0\""
|
|
1191
512
|
```
|
|
1192
513
|
|
|
1193
|
-
|
|
514
|
+
After this change:
|
|
1194
515
|
|
|
1195
516
|
```ruby
|
|
1196
|
-
|
|
517
|
+
ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0/24\""
|
|
1197
518
|
```
|
|
1198
519
|
|
|
1199
|
-
*
|
|
1200
|
-
|
|
1201
|
-
* Allow #increment and #decrement methods of `ActiveSupport::Cache::Store`
|
|
1202
|
-
subclasses to set new values.
|
|
1203
|
-
|
|
1204
|
-
Previously incrementing or decrementing an unset key would fail and return
|
|
1205
|
-
nil. A default will now be assumed and the key will be created.
|
|
1206
|
-
|
|
1207
|
-
*Andrej Blagojević*, *Eugene Kenny*
|
|
1208
|
-
|
|
1209
|
-
* Add `skip_nil:` support to `RedisCacheStore`
|
|
1210
|
-
|
|
1211
|
-
*Joey Paris*
|
|
1212
|
-
|
|
1213
|
-
* `ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true)` now
|
|
1214
|
-
correctly writes expired keys.
|
|
1215
|
-
|
|
1216
|
-
*Alan Savage*
|
|
1217
|
-
|
|
1218
|
-
* `ActiveSupport::ErrorReporter` now accepts and forward a `source:` parameter.
|
|
1219
|
-
|
|
1220
|
-
This allow libraries to signal the origin of the errors, and reporters
|
|
1221
|
-
to easily ignore some sources.
|
|
1222
|
-
|
|
1223
|
-
*Jean Boussier*
|
|
1224
|
-
|
|
1225
|
-
* Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
|
|
1226
|
-
|
|
1227
|
-
Add the method `ERB::Util.xml_name_escape` to escape dangerous characters
|
|
1228
|
-
in names of tags and names of attributes, following the specification of XML.
|
|
1229
|
-
|
|
1230
|
-
*Álvaro Martín Fraguas*
|
|
1231
|
-
|
|
1232
|
-
* Respect `ActiveSupport::Logger.new`'s `:formatter` keyword argument
|
|
1233
|
-
|
|
1234
|
-
The stdlib `Logger::new` allows passing a `:formatter` keyword argument to
|
|
1235
|
-
set the logger's formatter. Previously `ActiveSupport::Logger.new` ignored
|
|
1236
|
-
that argument by always setting the formatter to an instance of
|
|
1237
|
-
`ActiveSupport::Logger::SimpleFormatter`.
|
|
1238
|
-
|
|
1239
|
-
*Steven Harman*
|
|
1240
|
-
|
|
1241
|
-
* Deprecate preserving the pre-Ruby 2.4 behavior of `to_time`
|
|
1242
|
-
|
|
1243
|
-
With Ruby 2.4+ the default for +to_time+ changed from converting to the
|
|
1244
|
-
local system time to preserving the offset of the receiver. At the time Rails
|
|
1245
|
-
supported older versions of Ruby so a compatibility layer was added to assist
|
|
1246
|
-
in the migration process. From Rails 5.0 new applications have defaulted to
|
|
1247
|
-
the Ruby 2.4+ behavior and since Rails 7.0 now only supports Ruby 2.7+
|
|
1248
|
-
this compatibility layer can be safely removed.
|
|
520
|
+
*Taketo Takashima*
|
|
1249
521
|
|
|
1250
|
-
|
|
1251
|
-
setting is configured to `false` as that is the only scenario where the
|
|
1252
|
-
removal of the compatibility layer has any effect.
|
|
522
|
+
* Make `ActiveSupport::FileUpdateChecker` faster when checking many file-extensions.
|
|
1253
523
|
|
|
1254
|
-
*
|
|
1255
|
-
|
|
1256
|
-
* `Pathname.blank?` only returns true for `Pathname.new("")`
|
|
1257
|
-
|
|
1258
|
-
Previously it would end up calling `Pathname#empty?` which returned true
|
|
1259
|
-
if the path existed and was an empty directory or file.
|
|
1260
|
-
|
|
1261
|
-
That behavior was unlikely to be expected.
|
|
1262
|
-
|
|
1263
|
-
*Jean Boussier*
|
|
1264
|
-
|
|
1265
|
-
* Deprecate `Notification::Event`'s `#children` and `#parent_of?`
|
|
1266
|
-
|
|
1267
|
-
*John Hawthorn*
|
|
1268
|
-
|
|
1269
|
-
* Change the default serializer of `ActiveSupport::MessageVerifier` from
|
|
1270
|
-
`Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
|
|
1271
|
-
|
|
1272
|
-
Messages serialized with `Marshal` can still be read, but new messages will
|
|
1273
|
-
be serialized with `ActiveSupport::JSON`. For more information, see
|
|
1274
|
-
https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
|
|
1275
|
-
|
|
1276
|
-
*Saba Kiaei*, *David Buckley*, and *Jonathan Hefner*
|
|
1277
|
-
|
|
1278
|
-
* Change the default serializer of `ActiveSupport::MessageEncryptor` from
|
|
1279
|
-
`Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
|
|
1280
|
-
|
|
1281
|
-
Messages serialized with `Marshal` can still be read, but new messages will
|
|
1282
|
-
be serialized with `ActiveSupport::JSON`. For more information, see
|
|
1283
|
-
https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
|
|
1284
|
-
|
|
1285
|
-
*Zack Deveau*, *Martin Gingras*, and *Jonathan Hefner*
|
|
1286
|
-
|
|
1287
|
-
* Add `ActiveSupport::TestCase#stub_const` to stub a constant for the duration of a yield.
|
|
1288
|
-
|
|
1289
|
-
*DHH*
|
|
1290
|
-
|
|
1291
|
-
* Fix `ActiveSupport::EncryptedConfiguration` to be compatible with Psych 4
|
|
1292
|
-
|
|
1293
|
-
*Stephen Sugden*
|
|
1294
|
-
|
|
1295
|
-
* Improve `File.atomic_write` error handling
|
|
1296
|
-
|
|
1297
|
-
*Daniel Pepper*
|
|
1298
|
-
|
|
1299
|
-
* Fix `Class#descendants` and `DescendantsTracker#descendants` compatibility with Ruby 3.1.
|
|
1300
|
-
|
|
1301
|
-
[The native `Class#descendants` was reverted prior to Ruby 3.1 release](https://bugs.ruby-lang.org/issues/14394#note-33),
|
|
1302
|
-
but `Class#subclasses` was kept, breaking the feature detection.
|
|
1303
|
-
|
|
1304
|
-
*Jean Boussier*
|
|
524
|
+
*Jonathan del Strother*
|
|
1305
525
|
|
|
1306
|
-
Please check [
|
|
526
|
+
Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activesupport/CHANGELOG.md) for previous changes.
|