activesupport 7.2.3.1 → 8.1.4.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.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +584 -234
  3. data/lib/active_support/backtrace_cleaner.rb +72 -1
  4. data/lib/active_support/benchmark.rb +21 -0
  5. data/lib/active_support/benchmarkable.rb +3 -2
  6. data/lib/active_support/cache/file_store.rb +13 -2
  7. data/lib/active_support/cache/mem_cache_store.rb +17 -14
  8. data/lib/active_support/cache/memory_store.rb +9 -3
  9. data/lib/active_support/cache/redis_cache_store.rb +51 -34
  10. data/lib/active_support/cache/strategy/local_cache.rb +17 -8
  11. data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
  12. data/lib/active_support/cache.rb +86 -18
  13. data/lib/active_support/callbacks.rb +25 -11
  14. data/lib/active_support/class_attribute.rb +33 -0
  15. data/lib/active_support/code_generator.rb +9 -0
  16. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +8 -62
  17. data/lib/active_support/concurrency/share_lock.rb +0 -1
  18. data/lib/active_support/concurrency/thread_monitor.rb +55 -0
  19. data/lib/active_support/configurable.rb +34 -0
  20. data/lib/active_support/configuration_file.rb +15 -6
  21. data/lib/active_support/continuous_integration.rb +145 -0
  22. data/lib/active_support/core_ext/array/conversions.rb +3 -3
  23. data/lib/active_support/core_ext/array.rb +7 -7
  24. data/lib/active_support/core_ext/benchmark.rb +0 -16
  25. data/lib/active_support/core_ext/big_decimal.rb +1 -1
  26. data/lib/active_support/core_ext/class/attribute.rb +24 -18
  27. data/lib/active_support/core_ext/class.rb +2 -2
  28. data/lib/active_support/core_ext/date/conversions.rb +2 -0
  29. data/lib/active_support/core_ext/date.rb +5 -5
  30. data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -35
  31. data/lib/active_support/core_ext/date_time/calculations.rb +1 -0
  32. data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
  33. data/lib/active_support/core_ext/date_time.rb +5 -5
  34. data/lib/active_support/core_ext/digest.rb +1 -1
  35. data/lib/active_support/core_ext/enumerable.rb +8 -3
  36. data/lib/active_support/core_ext/erb/util.rb +3 -3
  37. data/lib/active_support/core_ext/file.rb +1 -1
  38. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
  39. data/lib/active_support/core_ext/hash/except.rb +0 -12
  40. data/lib/active_support/core_ext/hash.rb +8 -8
  41. data/lib/active_support/core_ext/integer.rb +3 -3
  42. data/lib/active_support/core_ext/kernel.rb +3 -3
  43. data/lib/active_support/core_ext/module/attr_internal.rb +3 -4
  44. data/lib/active_support/core_ext/module.rb +11 -11
  45. data/lib/active_support/core_ext/numeric.rb +3 -3
  46. data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
  47. data/lib/active_support/core_ext/object/json.rb +24 -11
  48. data/lib/active_support/core_ext/object/to_query.rb +7 -1
  49. data/lib/active_support/core_ext/object.rb +13 -13
  50. data/lib/active_support/core_ext/pathname.rb +2 -2
  51. data/lib/active_support/core_ext/range/compare_range.rb +2 -14
  52. data/lib/active_support/core_ext/range/overlap.rb +3 -3
  53. data/lib/active_support/core_ext/range/sole.rb +2 -0
  54. data/lib/active_support/core_ext/range.rb +4 -5
  55. data/lib/active_support/core_ext/string/filters.rb +2 -0
  56. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  57. data/lib/active_support/core_ext/string/multibyte.rb +10 -1
  58. data/lib/active_support/core_ext/string/output_safety.rb +27 -13
  59. data/lib/active_support/core_ext/string.rb +13 -13
  60. data/lib/active_support/core_ext/symbol.rb +1 -1
  61. data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
  62. data/lib/active_support/core_ext/time/calculations.rb +11 -2
  63. data/lib/active_support/core_ext/time/compatibility.rb +2 -27
  64. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  65. data/lib/active_support/core_ext/time.rb +5 -5
  66. data/lib/active_support/current_attributes/test_helper.rb +2 -2
  67. data/lib/active_support/current_attributes.rb +13 -10
  68. data/lib/active_support/delegation.rb +25 -44
  69. data/lib/active_support/dependencies/interlock.rb +11 -5
  70. data/lib/active_support/dependencies.rb +6 -2
  71. data/lib/active_support/deprecation/reporting.rb +4 -21
  72. data/lib/active_support/deprecation.rb +1 -1
  73. data/lib/active_support/duration.rb +20 -16
  74. data/lib/active_support/editor.rb +70 -0
  75. data/lib/active_support/encrypted_configuration.rb +20 -2
  76. data/lib/active_support/error_reporter.rb +76 -2
  77. data/lib/active_support/event_reporter/test_helper.rb +32 -0
  78. data/lib/active_support/event_reporter.rb +592 -0
  79. data/lib/active_support/evented_file_update_checker.rb +5 -2
  80. data/lib/active_support/execution_context.rb +75 -7
  81. data/lib/active_support/file_update_checker.rb +7 -5
  82. data/lib/active_support/gem_version.rb +3 -3
  83. data/lib/active_support/gzip.rb +1 -0
  84. data/lib/active_support/hash_with_indifferent_access.rb +44 -24
  85. data/lib/active_support/i18n_railtie.rb +19 -11
  86. data/lib/active_support/inflector/inflections.rb +34 -16
  87. data/lib/active_support/inflector/methods.rb +6 -22
  88. data/lib/active_support/inflector/transliterate.rb +18 -10
  89. data/lib/active_support/isolated_execution_state.rb +17 -17
  90. data/lib/active_support/json/decoding.rb +9 -3
  91. data/lib/active_support/json/encoding.rb +149 -19
  92. data/lib/active_support/log_subscriber.rb +2 -6
  93. data/lib/active_support/logger_thread_safe_level.rb +6 -3
  94. data/lib/active_support/message_encryptors.rb +52 -0
  95. data/lib/active_support/message_pack/extensions.rb +23 -1
  96. data/lib/active_support/message_verifiers.rb +52 -0
  97. data/lib/active_support/messages/rotation_coordinator.rb +9 -0
  98. data/lib/active_support/messages/rotator.rb +5 -0
  99. data/lib/active_support/messages/serializer_with_fallback.rb +1 -1
  100. data/lib/active_support/multibyte/chars.rb +8 -1
  101. data/lib/active_support/multibyte.rb +4 -0
  102. data/lib/active_support/notifications/fanout.rb +64 -43
  103. data/lib/active_support/notifications/instrumenter.rb +1 -1
  104. data/lib/active_support/notifications.rb +2 -2
  105. data/lib/active_support/number_helper/number_converter.rb +4 -1
  106. data/lib/active_support/number_helper/number_to_currency_converter.rb +1 -1
  107. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -4
  108. data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -7
  109. data/lib/active_support/number_helper/rounding_helper.rb +1 -1
  110. data/lib/active_support/number_helper.rb +22 -0
  111. data/lib/active_support/ordered_options.rb +2 -2
  112. data/lib/active_support/railtie.rb +32 -9
  113. data/lib/active_support/security_utils.rb +4 -5
  114. data/lib/active_support/structured_event_subscriber.rb +99 -0
  115. data/lib/active_support/subscriber.rb +0 -5
  116. data/lib/active_support/syntax_error_proxy.rb +9 -1
  117. data/lib/active_support/tagged_logging.rb +5 -0
  118. data/lib/active_support/test_case.rb +67 -6
  119. data/lib/active_support/testing/assertions.rb +118 -27
  120. data/lib/active_support/testing/autorun.rb +5 -0
  121. data/lib/active_support/testing/error_reporter_assertions.rb +17 -0
  122. data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
  123. data/lib/active_support/testing/isolation.rb +0 -2
  124. data/lib/active_support/testing/notification_assertions.rb +92 -0
  125. data/lib/active_support/testing/parallelization/worker.rb +7 -1
  126. data/lib/active_support/testing/parallelization.rb +17 -0
  127. data/lib/active_support/testing/tests_without_assertions.rb +1 -1
  128. data/lib/active_support/testing/time_helpers.rb +9 -4
  129. data/lib/active_support/time_with_zone.rb +36 -23
  130. data/lib/active_support/values/time_zone.rb +22 -13
  131. data/lib/active_support/xml_mini.rb +1 -2
  132. data/lib/active_support.rb +21 -9
  133. metadata +33 -17
  134. data/lib/active_support/core_ext/range/each.rb +0 -24
  135. data/lib/active_support/proxy_object.rb +0 -20
data/CHANGELOG.md CHANGED
@@ -1,453 +1,803 @@
1
- ## Rails 7.2.3.1 (March 23, 2026) ##
1
+ ## Rails 8.1.4.1 (November 03, 2026) ##
2
2
 
3
- * Reject scientific notation in NumberConverter
3
+ * `ActiveSupport::MessagePack` no longer deserializes an unsafe
4
+ `ActiveSupport::SafeBuffer` as `html_safe`.
4
5
 
5
- [CVE-2026-33176]
6
+ A `SafeBuffer` that was no longer `html_safe?`, for example after an
7
+ in-place `gsub!`, was deserialized as an `html_safe` `SafeBuffer`. It is now
8
+ serialized with an unsafe marker and deserialized as a `String`. Earlier
9
+ versions of Rails cannot read an unsafe buffer serialized this way.
10
+
11
+ [GHSA-2w9f-fxwj-w2qf]
6
12
 
7
13
  *Jean Boussier*
8
14
 
9
- * Fix `SafeBuffer#%` to preserve unsafe status
15
+ * `ActiveSupport::Inflector#safe_constantize` matches the constant name in a
16
+ `LoadError` message as a literal string instead of building a `Regexp`
17
+ from it.
10
18
 
11
- [CVE-2026-33170]
19
+ The name's segments were interpolated unescaped into the pattern, so input
20
+ that reaches `safe_constantize`, such as the channel identifier in an Action
21
+ Cable subscribe command, chose the source passed to the regexp compiler.
12
22
 
13
- *Jean Boussier*
23
+ [GHSA-8474-xrp6-wh69]
14
24
 
15
- * Improve performance of NumberToDelimitedConverter
25
+ *Jeremy Daer*
16
26
 
17
- [CVE-2026-33169]
27
+ ## Rails 8.1.4 (September 24, 2026) ##
18
28
 
19
- *Jean Boussier*
29
+ * Fix the debug error page rendering for `SyntaxError`s with multi-line messages.
20
30
 
31
+ *Marco Roth*
21
32
 
22
- ## Rails 7.2.3 (October 28, 2025) ##
33
+ * Make `ActiveSupport::JSON.decode` compatible with the upcoming `json` 3.0 gem.
23
34
 
24
- * Fix `Enumerable#sole` to return the full tuple instead of just the first element of the tuple.
35
+ *Earlopain*
25
36
 
26
- *Olivier Bellone*
37
+ * Fix `number_to_human_size` crashing for sizes above a terabyte by supporting
38
+ petabyte, exabyte, and zettabyte storage units.
27
39
 
28
- * Fix parallel tests hanging when worker processes die abruptly.
40
+ *Kenta Ishizaki*
29
41
 
30
- Previously, if a worker process was killed (e.g., OOM killed, `kill -9`) during parallel
31
- test execution, the test suite would hang forever waiting for the dead worker.
42
+ * Fix `Range#sole` raising `NoMethodError` when the enumerable core extension
43
+ isn't already loaded.
32
44
 
33
- *Joshua Young*
45
+ *Kenta Ishizaki*
34
46
 
35
- * `ActiveSupport::FileUpdateChecker` does not depend on `Time.now` to prevent unnecessary reloads with time travel test helpers
47
+ * Fix `ActiveSupport::Cache::FileStore` raising `NameError` for `FileUtils`
48
+ when `fileutils` isn't already loaded.
36
49
 
37
- *Jan Grodowski*
50
+ *Kenta Ishizaki*
38
51
 
39
- * Fix `ActiveSupport::BroadcastLogger` from executing a block argument for each logger (tagged, info, etc.).
52
+ * Fix `Enumerable#in_order_of` with `filter: true` dropping `nil` elements
53
+ explicitly named in the series.
40
54
 
41
- *Jared Armstrong*
55
+ *Kenta Ishizaki*
42
56
 
43
- * Fix `ActiveSupport::HashWithIndifferentAccess#transform_keys!` removing defaults.
57
+ * Keep `HashWithIndifferentAccess#filter` returning a `HashWithIndifferentAccess`
58
+ instead of a plain `Hash`.
44
59
 
45
- *Hartley McGuire*
60
+ *Kenta Ishizaki*
46
61
 
47
- * Fix `ActiveSupport::HashWithIndifferentAccess#tranform_keys!` to handle collisions.
62
+ * Fix `number_to_human` and `number_to_human_size` crashing when `:precision` is `nil`.
48
63
 
49
- If the transformation would result in a key equal to another not yet transformed one,
50
- it would result in keys being lost.
64
+ *Kenta Ishizaki*
51
65
 
52
- Before:
66
+ * Fix `ActiveSupport::InheritableOptions#to_h` to recursively flatten nested
67
+ `InheritableOptions` parents.
53
68
 
54
- ```ruby
55
- >> {a: 1, b: 2}.with_indifferent_access.transform_keys!(&:succ)
56
- => {"c" => 1}
57
- ```
69
+ *Andrew Novoselac*
58
70
 
59
- After:
71
+ * Fix `ActiveSupport::StructuredEventSubscriber.debug_only` leaking debug-only
72
+ methods across subscriber subclasses.
60
73
 
61
- ```ruby
62
- >> {a: 1, b: 2}.with_indifferent_access.transform_keys!(&:succ)
63
- => {"c" => 1, "d" => 2}
64
- ```
74
+ *Kenta Ishizaki*
65
75
 
66
- *Jason T Johnson*, *Jean Boussier*
76
+ * Fix `ActiveSupport::Inflector#transliterate` mutating the caller's string.
67
77
 
68
- * Fix `ActiveSupport::Cache::MemCacheStore#read_multi` to handle network errors.
78
+ *Kenta Ishizaki*
69
79
 
70
- This method specifically wasn't handling network errors like other codepaths.
80
+ * Fix `Hash.from_xml` raising `Date::Error` on `type="date"` values surrounded
81
+ by whitespace.
71
82
 
72
- *Alessandro Dal Grande*
83
+ *Kenta Ishizaki*
73
84
 
74
- * Fix Active Support Cache `fetch_multi` when local store is active.
85
+ * Fix `Time#advance` and `DateTime#advance` mutating the options hash passed
86
+ by the caller.
75
87
 
76
- `fetch_multi` now properly yield to the provided block for missing entries
77
- that have been recorded as such in the local store.
88
+ *Kenta Ishizaki*
78
89
 
79
- *Jean Boussier*
90
+ * Fix `ActiveSupport::Cache::MemoryStore#cleanup` raising `NoMethodError` when
91
+ used with a non-`DupCoder` serializer.
80
92
 
81
- * Fix execution wrapping to report all exceptions, including `Exception`.
93
+ *Kenta Ishizaki*
82
94
 
83
- If a more serious error like `SystemStackError` or `NoMemoryError` happens,
84
- the error reporter should be able to report these kinds of exceptions.
95
+ * Fix `String#truncate` with `:separator` misbehaving when the `:omission` is
96
+ longer than the target length.
85
97
 
86
- *Gannon McGibbon*
98
+ *Kenta Ishizaki*
87
99
 
88
- * Fix `RedisCacheStore` and `MemCacheStore` to also handle connection pool related errors.
100
+ * Fix `ActiveSupport::Cache::Store#delete_multi` mutating the names array passed
101
+ by the caller.
89
102
 
90
- These errors are rescued and reported to `Rails.error`.
103
+ *Kenta Ishizaki*
91
104
 
92
- *Jean Boussier*
105
+ * Fix `number_to_currency` crashing on a negative number when `:precision` is `nil`.
93
106
 
94
- * Fix `ActiveSupport::Cache#read_multi` to respect version expiry when using local cache.
107
+ *Kenta Ishizaki*
95
108
 
96
- *zzak*
109
+ * Fix `TimeZone#strptime` with `%s` dropping the sub-second fraction of the timestamp.
97
110
 
98
- * Fix `ActiveSupport::MessageVerifier` and `ActiveSupport::MessageEncryptor` configuration of `on_rotation` callback.
111
+ *Kenta Ishizaki*
99
112
 
100
- ```ruby
101
- verifier.rotate(old_secret).on_rotation { ... }
102
- ```
113
+ * Fix `HashWithIndifferentAccess.new` dropping a falsy (`false` or `0`) default
114
+ value from the source hash.
103
115
 
104
- Now both work as documented.
116
+ *Kenta Ishizaki*
105
117
 
106
- *Jean Boussier*
118
+ * Fix `Range#include?` and `Range#===` raising on exclusive non-integer sub-ranges.
107
119
 
108
- * Fix `ActiveSupport::MessageVerifier` to always be able to verify both URL-safe and URL-unsafe payloads.
120
+ *Kenta Ishizaki*
109
121
 
110
- This is to allow transitioning seemlessly from either configuration without immediately invalidating
111
- all previously generated signed messages.
122
+ * Fix `number_to_delimited` corrupting numbers that begin with a `+` or `-` sign.
112
123
 
113
- *Jean Boussier*, *Florent Beaurain*, *Ali Sepehri*
124
+ *Kenta Ishizaki*
114
125
 
115
- * Fix `cache.fetch` to honor the provided expiry when `:race_condition_ttl` is used.
126
+ * Fix `ActiveSupport::InheritableOptions#==` raising `NoMethodError` when compared
127
+ with a non-Hash object.
116
128
 
117
- ```ruby
118
- cache.fetch("key", expires_in: 1.hour, race_condition_ttl: 5.second) do
119
- "something"
120
- end
121
- ```
129
+ *Kenta Ishizaki*
130
+
131
+ * Fix `Enumerable#in_order_of` with `filter: false` dropping elements whose keyed
132
+ value is `nil`.
122
133
 
123
- In the above example, the final cache entry would have a 10 seconds TTL instead
124
- of the requested 1 hour.
134
+ *Hammad Khan*
125
135
 
126
- *Dhia*
136
+ * Stop the DRb service when shutting down parallel test workers, preventing it
137
+ from lingering after the test run.
127
138
 
128
- * Better handle procs with splat arguments in `set_callback`.
139
+ *Shuta Mugikura*
129
140
 
130
- *Radamés Roriz*
141
+ * Preserve the encoding of `ActiveSupport::SafeBuffer` values round-tripped through
142
+ `ActiveSupport::MessagePack`.
131
143
 
132
- * Fix `String#mb_chars` to not mutate the receiver.
144
+ *Rafael Mendonça França*
133
145
 
134
- Previously it would call `force_encoding` on the receiver,
135
- now it dups the receiver first.
146
+ * Fix `number_to_phone` without an area code stripping a leading delimiter when the
147
+ number itself coincidentally starts with the delimiter string.
136
148
 
137
- *Jean Boussier*
149
+ *Tahsin Hasan*
138
150
 
139
- * Improve `ErrorSubscriber` to also mark error causes as reported.
151
+ * Update `ActiveSupport::TimeZone` mappings to use the current IANA identifiers
152
+ `Europe/Kyiv` (was `Europe/Kiev`) and `Asia/Yangon` (was `Asia/Rangoon`).
140
153
 
141
- This avoid some cases of errors being reported twice, notably in views because of how
142
- errors are wrapped in `ActionView::Template::Error`.
154
+ *tsymbalenkovlad*
143
155
 
144
- *Jean Boussier*
156
+ * Use the faster string-based delimiter logic by default in `number_to_delimited`,
157
+ instead of the regular expression fallback.
158
+
159
+ *Shinichi Maeshima*
145
160
 
146
- * Fix `Module#module_parent_name` to return the correct name after the module has been named.
161
+ * Preserve the requested key order in `ActiveSupport::Cache::Store#fetch_multi`
162
+ when a local cache is active.
147
163
 
148
- When called on an anonymous module, the return value wouldn't change after the module was given a name
149
- later by being assigned to a constant.
164
+ Previously, if some keys were served from the local cache and others from the
165
+ underlying store, `fetch_multi` returned the local cache hits first instead of
166
+ following the order of the requested keys.
167
+
168
+ *Mueez Afzal*
169
+
170
+ * Fix `String#parameterize` raising `TypeError` when `separator` is `nil`.
171
+
172
+ `parameterize` already treats a `nil` separator the same as an empty one when
173
+ squeezing and trimming separators, but raised `TypeError` before reaching that
174
+ point. A `nil` separator now behaves like `""`, removing the unwanted characters.
150
175
 
151
176
  ```ruby
152
- mod = Module.new
153
- mod.module_parent_name # => "Object"
154
- MyModule::Something = mod
155
- mod.module_parent_name # => "MyModule"
177
+ "Donald E. Knuth".parameterize(separator: nil) # => "donaldeknuth"
156
178
  ```
157
179
 
158
- *Jean Boussier*
180
+ *Hammad Khan*
159
181
 
160
- * Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceeded by multibyte characters.
182
+ * Add `RedisClient::Error` to `ActiveSupport::Cache::RedisCacheStore`'s failsafe rescue list.
161
183
 
162
- *Martin Emde*
184
+ The redis-rb gem normally translates `RedisClient::*` errors into `Redis::*` errors but in
185
+ some rare cases, such as when using sentinels, `RedisClient::*` errors may slip through.
163
186
 
187
+ *David Arrunategui*
164
188
 
165
- ## Rails 7.2.2.2 (August 13, 2025) ##
189
+ * Fix `ActiveSupport::Duration#in_minutes`, `#in_hours`, `#in_days`,
190
+ `#in_weeks`, `#in_months`, and `#in_years` truncating sub-second precision.
166
191
 
167
- * No changes.
192
+ These methods divided the duration's integer second count (`in_seconds`,
193
+ aliased to `to_i`) instead of its exact value, so any fractional second was
194
+ silently dropped before the conversion.
195
+
196
+ ```ruby
197
+ # Before
198
+ 90.5.seconds.in_minutes # => 1.5
168
199
 
200
+ # After
201
+ 90.5.seconds.in_minutes # => 1.5083333333333333
202
+ ```
169
203
 
170
- ## Rails 7.2.2.1 (December 10, 2024) ##
204
+ *Kenta Ishizaki*
171
205
 
172
- * No changes.
206
+ * Fix JSON encoding of non-String Hash keys.
173
207
 
208
+ The old encoder would simply call `to_s` on them, the newer encoder
209
+ would incorrectly call `as_json` instead.
174
210
 
175
- ## Rails 7.2.2 (October 30, 2024) ##
211
+ In the case of `Time`, `DateTime` and `TimeWithZone` this would result
212
+ in different serialization of time keys: `"2009-01-01T12:30:00.000Z"` (arguably better)
213
+ instead of `"2009-01-01 12:30:00 UTC"` (how it used to be).
176
214
 
177
- * Include options when instrumenting `ActiveSupport::Cache::Store#delete` and `ActiveSupport::Cache::Store#delete_multi`.
215
+ *Kenta Ishizaki*
178
216
 
179
- *Adam Renberg Tamm*
217
+ * Fix `number_to_phone` dropping only the first character of a
218
+ multi-character `:delimiter` when no area code is present.
180
219
 
181
- * Print test names when running `rails test -v` for parallel tests.
220
+ The leading delimiter produced by an empty first capture group was
221
+ stripped with `slice!(0, 1)`, which assumed a single-character
222
+ delimiter. Multi-character (and multibyte) delimiters now work:
182
223
 
183
- *John Hawthorn*, *Abeid Ahmed*
224
+ number_to_phone(5551234, delimiter: " - ") # => "555 - 1234"
225
+ # was "- 555 - 1234"
184
226
 
227
+ *Kenta Ishizaki*
185
228
 
186
- ## Rails 7.2.1.2 (October 23, 2024) ##
229
+ * Fix `titleize` inflector to consider Unicode characters
187
230
 
188
- * No changes.
231
+ ```ruby
232
+ "ćasim đipa".titleize # => "Ćasim Đipa"
233
+ ```
234
+
235
+ *Eldin Guzin*
189
236
 
190
237
 
191
- ## Rails 7.2.1.1 (October 15, 2024) ##
238
+ ## Rails 8.1.3.1 (July 29, 2026) ##
192
239
 
193
240
  * No changes.
194
241
 
195
242
 
196
- ## Rails 7.2.1 (August 22, 2024) ##
243
+ ## Rails 8.1.3 (March 24, 2026) ##
197
244
 
198
- * No changes.
245
+ * Fix `JSONGemCoderEncoder` to correctly serialize custom object hash keys.
199
246
 
247
+ When hash keys are custom objects whose `as_json` returns a Hash,
248
+ the encoder now calls `to_s` on the original key object instead of
249
+ on the `as_json` result.
200
250
 
201
- ## Rails 7.2.0 (August 09, 2024) ##
251
+ Before:
252
+ hash = {CustomKey.new(123) => "value"}
253
+ hash.to_json # => {"{:id=>123}":"value"}
202
254
 
203
- * Fix `delegate_missing_to allow_nil: true` when called with implict self
255
+ After:
256
+ hash.to_json # => {"custom_123":"value"}
204
257
 
205
- ```ruby
206
- class Person
207
- delegate_missing_to :address, allow_nil: true
258
+ *Dan Sharp*
208
259
 
209
- def address
210
- nil
211
- end
260
+ * Fix inflections to better handle overlapping acronyms.
212
261
 
213
- def berliner?
214
- city == "Berlin"
215
- end
262
+ ```ruby
263
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
264
+ inflect.acronym "USD"
265
+ inflect.acronym "USDC"
216
266
  end
217
267
 
218
- Person.new.city # => nil
219
- Person.new.berliner? # undefined local variable or method `city' for an instance of Person (NameError)
268
+ "USDC".underscore # => "usdc"
220
269
  ```
221
270
 
271
+ *Said Kaldybaev*
272
+
273
+ * Silence Dalli 4.0+ warning when using `ActiveSupport::Cache::MemCacheStore`.
274
+
275
+ *zzak*
276
+
277
+
278
+ ## Rails 8.1.2.1 (March 23, 2026) ##
279
+
280
+ * Reject scientific notation in NumberConverter
281
+
282
+ [CVE-2026-33176]
283
+
222
284
  *Jean Boussier*
223
285
 
224
- * Add `logger` as a dependency since it is a bundled gem candidate for Ruby 3.5
286
+ * Fix `SafeBuffer#%` to preserve unsafe status
225
287
 
226
- *Earlopain*
288
+ [CVE-2026-33170]
227
289
 
228
- * Define `Digest::UUID.nil_uuid`, which returns the so-called nil UUID.
290
+ *Jean Boussier*
229
291
 
230
- *Xavier Noria*
292
+ * Improve performance of NumberToDelimitedConverter
293
+
294
+ [CVE-2026-33169]
295
+
296
+ *Jean Boussier*
231
297
 
232
- * Support `duration` type in `ActiveSupport::XmlMini`.
233
298
 
234
- *heka1024*
299
+ ## Rails 8.1.2 (January 08, 2026) ##
235
300
 
236
- * Remove deprecated `ActiveSupport::Notifications::Event#children` and `ActiveSupport::Notifications::Event#parent_of?`.
301
+ * Make `delegate` and `delegate_missing_to` work in BasicObject subclasses.
237
302
 
238
303
  *Rafael Mendonça França*
239
304
 
240
- * Remove deprecated support to call the following methods without passing a deprecator:
305
+ * Fix Inflectors when using a locale that fallbacks to `:en`.
241
306
 
242
- - `deprecate`
243
- - `deprecate_constant`
244
- - `ActiveSupport::Deprecation::DeprecatedObjectProxy.new`
245
- - `ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new`
246
- - `ActiveSupport::Deprecation::DeprecatedConstantProxy.new`
247
- - `assert_deprecated`
248
- - `assert_not_deprecated`
249
- - `collect_deprecations`
307
+ *Said Kaldybaev*
250
308
 
251
- *Rafael Mendonça França*
309
+ * Fix `ActiveSupport::TimeWithZone#as_json` to consistently return UTF-8 strings.
252
310
 
253
- * Remove deprecated `ActiveSupport::Deprecation` delegation to instance.
311
+ Previously the returned string would sometime be encoded in US-ASCII, which in
312
+ some cases may be problematic.
254
313
 
255
- *Rafael Mendonça França*
314
+ Now the method consistently always return UTF-8 strings.
256
315
 
257
- * Remove deprecated `SafeBuffer#clone_empty`.
316
+ *Jean Boussier*
258
317
 
259
- *Rafael Mendonça França*
318
+ * Fix `TimeWithZone#xmlschema` when wrapping a `DateTime` instance in local time.
260
319
 
261
- * Remove deprecated `#to_default_s` from `Array`, `Date`, `DateTime` and `Time`.
320
+ Previously it would return an invalid time.
262
321
 
263
- *Rafael Mendonça França*
322
+ *Dmytro Rymar*
264
323
 
265
- * Remove deprecated support to passing `Dalli::Client` instances to `MemCacheStore`.
324
+ * Implement LocalCache strategy on `ActiveSupport::Cache::MemoryStore`. The memory store
325
+ needs to respond to the same interface as other cache stores (e.g. `ActiveSupport::NullStore`).
266
326
 
267
- *Rafael Mendonça França*
327
+ *Mikey Gough*
268
328
 
269
- * Remove deprecated `config.active_support.use_rfc4122_namespaced_uuids`.
329
+ * Fix `ActiveSupport::Inflector.humanize` with international characters.
270
330
 
271
- *Rafael Mendonça França*
331
+ ```ruby
332
+ ActiveSupport::Inflector.humanize("áÉÍÓÚ") # => "Áéíóú"
333
+ ActiveSupport::Inflector.humanize("аБВГДЕ") # => "Абвгде"
334
+ ```
272
335
 
273
- * Remove deprecated `config.active_support.remove_deprecated_time_with_zone_name`.
336
+ *Jose Luis Duran*
274
337
 
275
- *Rafael Mendonça França*
276
338
 
277
- * Remove deprecated `config.active_support.disable_to_s_conversion`.
339
+ ## Rails 8.1.1 (October 28, 2025) ##
278
340
 
279
- *Rafael Mendonça França*
341
+ * No changes.
280
342
 
281
- * Remove deprecated support to bolding log text with positional boolean in `ActiveSupport::LogSubscriber#color`.
343
+
344
+ ## Rails 8.1.0 (October 22, 2025) ##
345
+
346
+ * Remove deprecated passing a Time object to `Time#since`.
282
347
 
283
348
  *Rafael Mendonça França*
284
349
 
285
- * Remove deprecated constants `ActiveSupport::LogSubscriber::CLEAR` and `ActiveSupport::LogSubscriber::BOLD`.
350
+ * Remove deprecated `Benchmark.ms` method. It is now defined in the `benchmark` gem.
286
351
 
287
352
  *Rafael Mendonça França*
288
353
 
289
- * Remove deprecated support for `config.active_support.cache_format_version = 6.1`.
354
+ * Remove deprecated addition for `Time` instances with `ActiveSupport::TimeWithZone`.
290
355
 
291
356
  *Rafael Mendonça França*
292
357
 
293
- * Remove deprecated `:pool_size` and `:pool_timeout` options for the cache storage.
358
+ * Remove deprecated support for `to_time` to preserve the system local time. It will now always preserve the receiver
359
+ timezone.
294
360
 
295
361
  *Rafael Mendonça França*
296
362
 
297
- * Warn on tests without assertions.
363
+ * Deprecate `config.active_support.to_time_preserves_timezone`.
298
364
 
299
- `ActiveSupport::TestCase` now warns when tests do not run any assertions.
300
- This is helpful in detecting broken tests that do not perform intended assertions.
365
+ *Rafael Mendonça França*
301
366
 
302
- *fatkodima*
367
+ * Standardize event name formatting in `assert_event_reported` error messages.
303
368
 
304
- * Support `hexBinary` type in `ActiveSupport::XmlMini`.
369
+ The event name in failure messages now uses `.inspect` (e.g., `name: "user.created"`)
370
+ to match `assert_events_reported` and provide type clarity between strings and symbols.
371
+ This only affects tests that assert on the failure message format itself.
305
372
 
306
- *heka1024*
373
+ *George Ma*
307
374
 
308
- * Deprecate `ActiveSupport::ProxyObject` in favor of Ruby's built-in `BasicObject`.
375
+ * Fix `Enumerable#sole` to return the full tuple instead of just the first element of the tuple.
309
376
 
310
- *Earlopain*
377
+ *Olivier Bellone*
378
+
379
+ * Fix parallel tests hanging when worker processes die abruptly.
311
380
 
312
- * `stub_const` now accepts a `exists: false` parameter to allow stubbing missing constants.
381
+ Previously, if a worker process was killed (e.g., OOM killed, `kill -9`) during parallel
382
+ test execution, the test suite would hang forever waiting for the dead worker.
313
383
 
314
- *Jean Boussier*
384
+ *Joshua Young*
315
385
 
316
- * Make `ActiveSupport::BacktraceCleaner` copy filters and silencers on dup and clone.
386
+ * Add `config.active_support.escape_js_separators_in_json`.
317
387
 
318
- Previously the copy would still share the internal silencers and filters array,
319
- causing state to leak.
388
+ Introduce a new framework default to skip escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON.
320
389
 
321
- *Jean Boussier*
390
+ Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019.
391
+ As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset.
322
392
 
323
- * Updating Astana with Western Kazakhstan TZInfo identifier.
393
+ *Étienne Barrié*, *Jean Boussier*
324
394
 
325
- *Damian Nelson*
395
+ * Fix `NameError` when `class_attribute` is defined on instance singleton classes.
326
396
 
327
- * Add filename support for `ActiveSupport::Logger.logger_outputs_to?`.
397
+ Previously, calling `class_attribute` on an instance's singleton class would raise
398
+ a `NameError` when accessing the attribute through the instance.
328
399
 
329
400
  ```ruby
330
- logger = Logger.new('/var/log/rails.log')
331
- ActiveSupport::Logger.logger_outputs_to?(logger, '/var/log/rails.log')
401
+ object = MyClass.new
402
+ object.singleton_class.class_attribute :foo, default: "bar"
403
+ object.foo # previously raised NameError, now returns "bar"
332
404
  ```
333
405
 
334
- *Christian Schmidt*
406
+ *Joshua Young*
335
407
 
336
- * Include `IPAddr#prefix` when serializing an `IPAddr` using the
337
- `ActiveSupport::MessagePack` serializer.
408
+ * Introduce `ActiveSupport::Testing::EventReporterAssertions#with_debug_event_reporting`
409
+ to enable event reporter debug mode in tests.
338
410
 
339
- This change is backward and forward compatible — old payloads can
340
- still be read, and new payloads will be readable by older versions of Rails.
411
+ The previous way to enable debug mode is by using `#with_debug` on the
412
+ event reporter itself, which is too verbose. This new helper will help
413
+ clear up any confusion on how to test debug events.
341
414
 
342
- *Taiki Komaba*
415
+ *Gannon McGibbon*
343
416
 
344
- * Add `default:` support for `ActiveSupport::CurrentAttributes.attribute`.
417
+ * Add `ActiveSupport::StructuredEventSubscriber` for consuming notifications and
418
+ emitting structured event logs. Events may be emitted with the `#emit_event`
419
+ or `#emit_debug_event` methods.
345
420
 
346
421
  ```ruby
347
- class Current < ActiveSupport::CurrentAttributes
348
- attribute :counter, default: 0
422
+ class MyStructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber
423
+ def notification(event)
424
+ emit_event("my.notification", data: 1)
425
+ end
349
426
  end
350
427
  ```
351
428
 
352
- *Sean Doyle*
429
+ *Adrianna Chang*
430
+
431
+ * `ActiveSupport::FileUpdateChecker` does not depend on `Time.now` to prevent unecessary reloads with time travel test helpers
432
+
433
+ *Jan Grodowski*
434
+
435
+ * Add `ActiveSupport::Cache::Store#namespace=` and `#namespace`.
436
+
437
+ Can be used as an alternative to `Store#clear` in some situations such as parallel
438
+ testing.
439
+
440
+ *Nick Schwaderer*
441
+
442
+ * Create `parallel_worker_id` helper for running parallel tests. This allows users to
443
+ know which worker they are currently running in.
444
+
445
+ *Nick Schwaderer*
446
+
447
+ * Make the cache of `ActiveSupport::Cache::Strategy::LocalCache::Middleware` updatable.
448
+
449
+ If the cache client at `Rails.cache` of a booted application changes, the corresponding
450
+ mounted middleware needs to update in order for request-local caches to be setup properly.
451
+ Otherwise, redundant cache operations will erroneously hit the datastore.
353
452
 
354
- * Yield instance to `Object#with` block.
453
+ *Gannon McGibbon*
454
+
455
+ * Add `assert_events_reported` test helper for `ActiveSupport::EventReporter`.
456
+
457
+ This new assertion allows testing multiple events in a single block, regardless of order:
355
458
 
356
459
  ```ruby
357
- client.with(timeout: 5_000) do |c|
358
- c.get("/commits")
460
+ assert_events_reported([
461
+ { name: "user.created", payload: { id: 123 } },
462
+ { name: "email.sent", payload: { to: "user@example.com" } }
463
+ ]) do
464
+ create_user_and_send_welcome_email
359
465
  end
360
466
  ```
361
467
 
362
- *Sean Doyle*
468
+ *George Ma*
363
469
 
364
- * Use logical core count instead of physical core count to determine the
365
- default number of workers when parallelizing tests.
470
+ * Add `ActiveSupport::TimeZone#standard_name` method.
366
471
 
367
- *Jonathan Hefner*
472
+ ``` ruby
473
+ zone = ActiveSupport::TimeZone['Hawaii']
474
+ # Old way
475
+ ActiveSupport::TimeZone::MAPPING[zone.name]
476
+ # New way
477
+ zone.standard_name # => 'Pacific/Honolulu'
478
+ ```
368
479
 
369
- * Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
480
+ *Bogdan Gusiev*
370
481
 
371
- There is a bug in the current implementation of #travel_to:
372
- it remembers a timezone of its argument, and all stubbed methods start
373
- returning results in that remembered timezone. However, the expected
374
- behavior is to return results in a system timezone.
482
+ * Add Structured Event Reporter, accessible via `Rails.event`.
375
483
 
376
- *Aleksei Chernenkov*
484
+ The Event Reporter provides a unified interface for producing structured events in Rails
485
+ applications:
377
486
 
378
- * Add `ErrorReported#unexpected` to report precondition violations.
487
+ ```ruby
488
+ Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
489
+ ```
379
490
 
380
- For example:
491
+ It supports adding tags to events:
381
492
 
382
493
  ```ruby
383
- def edit
384
- if published?
385
- Rails.error.unexpected("[BUG] Attempting to edit a published article, that shouldn't be possible")
386
- return false
494
+ Rails.event.tagged("graphql") do
495
+ # Event includes tags: { graphql: true }
496
+ Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
497
+ end
498
+ ```
499
+
500
+ As well as context:
501
+ ```ruby
502
+ # All events will contain context: {request_id: "abc123", shop_id: 456}
503
+ Rails.event.set_context(request_id: "abc123", shop_id: 456)
504
+ ```
505
+
506
+ Events are emitted to subscribers. Applications register subscribers to
507
+ control how events are serialized and emitted. Subscribers must implement
508
+ an `#emit` method, which receives the event hash:
509
+
510
+ ```ruby
511
+ class LogSubscriber
512
+ def emit(event)
513
+ payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ")
514
+ source_location = event[:source_location]
515
+ log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}"
516
+ Rails.logger.info(log)
387
517
  end
388
- # ...
389
518
  end
390
519
  ```
391
520
 
392
- The above will raise an error in development and test, but only report the error in production.
521
+ *Adrianna Chang*
522
+
523
+ * Make `ActiveSupport::Logger` `#freeze`-friendly.
524
+
525
+ *Joshua Young*
526
+
527
+ * Make `ActiveSupport::Gzip.compress` deterministic based on input.
528
+
529
+ `ActiveSupport::Gzip.compress` used to include a timestamp in the output,
530
+ causing consecutive calls with the same input data to have different output
531
+ if called during different seconds. It now always sets the timestamp to `0`
532
+ so that the output is identical for any given input.
533
+
534
+ *Rob Brackett*
535
+
536
+ * Given an array of `Thread::Backtrace::Location` objects, the new method
537
+ `ActiveSupport::BacktraceCleaner#clean_locations` returns an array with the
538
+ clean ones:
539
+
540
+ ```ruby
541
+ clean_locations = backtrace_cleaner.clean_locations(caller_locations)
542
+ ```
543
+
544
+ Filters and silencers receive strings as usual. However, the `path`
545
+ attributes of the locations in the returned array are the original,
546
+ unfiltered ones, since locations are immutable.
547
+
548
+ *Xavier Noria*
549
+
550
+ * Improve `CurrentAttributes` and `ExecutionContext` state managment in test cases.
551
+
552
+ Previously these two global state would be entirely cleared out whenever calling
553
+ into code that is wrapped by the Rails executor, typically Action Controller or
554
+ Active Job helpers:
555
+
556
+ ```ruby
557
+ test "#index works" do
558
+ CurrentUser.id = 42
559
+ get :index
560
+ CurrentUser.id == nil
561
+ end
562
+ ```
563
+
564
+ Now re-entering the executor properly save and restore that state.
393
565
 
394
566
  *Jean Boussier*
395
567
 
396
- * Make the order of read_multi and write_multi notifications for `Cache::Store#fetch_multi` operations match the order they are executed in.
568
+ * The new method `ActiveSupport::BacktraceCleaner#first_clean_location`
569
+ returns the first clean location of the caller's call stack, or `nil`.
570
+ Locations are `Thread::Backtrace::Location` objects. Useful when you want to
571
+ report the application-level location where something happened as an object.
397
572
 
398
- *Adam Renberg Tamm*
573
+ *Xavier Noria*
399
574
 
400
- * Make return values of `Cache::Store#write` consistent.
575
+ * FileUpdateChecker and EventedFileUpdateChecker ignore changes in Gem.path now.
401
576
 
402
- The return value was not specified before. Now it returns `true` on a successful write,
403
- `nil` if there was an error talking to the cache backend, and `false` if the write failed
404
- for another reason (e.g. the key already exists and `unless_exist: true` was passed).
577
+ *Ermolaev Andrey*, *zzak*
405
578
 
406
- *Sander Verdonschot*
579
+ * The new method `ActiveSupport::BacktraceCleaner#first_clean_frame` returns
580
+ the first clean frame of the caller's backtrace, or `nil`. Useful when you
581
+ want to report the application-level frame where something happened as a
582
+ string.
407
583
 
408
- * Fix logged cache keys not always matching actual key used by cache action.
584
+ *Xavier Noria*
409
585
 
410
- *Hartley McGuire*
586
+ * Always clear `CurrentAttributes` instances.
411
587
 
412
- * Improve error messages of `assert_changes` and `assert_no_changes`.
588
+ Previously `CurrentAttributes` instance would be reset at the end of requests.
589
+ Meaning its attributes would be re-initialized.
413
590
 
414
- `assert_changes` error messages now display objects with `.inspect` to make it easier
415
- to differentiate nil from empty strings, strings from symbols, etc.
416
- `assert_no_changes` error messages now surface the actual value.
591
+ This is problematic because it assume these objects don't hold any state
592
+ other than their declared attribute, which isn't always the case, and
593
+ can lead to state leak across request.
417
594
 
418
- *pcreux*
595
+ Now `CurrentAttributes` instances are abandoned at the end of a request,
596
+ and a new instance is created at the start of the next request.
419
597
 
420
- * Fix `#to_fs(:human_size)` to correctly work with negative numbers.
598
+ *Jean Boussier*, *Janko Marohnić*
421
599
 
422
- *Earlopain*
600
+ * Add public API for `before_fork_hook` in parallel testing.
423
601
 
424
- * Fix `BroadcastLogger#dup` so that it duplicates the logger's `broadcasts`.
602
+ Introduces a public API for calling the before fork hooks implemented by parallel testing.
425
603
 
426
- *Andrew Novoselac*
604
+ ```ruby
605
+ parallelize_before_fork do
606
+ # perform an action before test processes are forked
607
+ end
608
+ ```
609
+
610
+ *Eileen M. Uchitelle*
611
+
612
+ * Implement ability to skip creating parallel testing databases.
613
+
614
+ With parallel testing, Rails will create a database per process. If this isn't
615
+ desirable or you would like to implement databases handling on your own, you can
616
+ now turn off this default behavior.
617
+
618
+ To skip creating a database per process, you can change it via the
619
+ `parallelize` method:
620
+
621
+ ```ruby
622
+ parallelize(workers: 10, parallelize_databases: false)
623
+ ```
624
+
625
+ or via the application configuration:
626
+
627
+ ```ruby
628
+ config.active_support.parallelize_databases = false
629
+ ```
630
+
631
+ *Eileen M. Uchitelle*
632
+
633
+ * Allow to configure maximum cache key sizes
634
+
635
+ When the key exceeds the configured limit (250 bytes by default), it will be truncated and
636
+ the digest of the rest of the key appended to it.
637
+
638
+ Note that previously `ActiveSupport::Cache::RedisCacheStore` allowed up to 1kb cache keys before
639
+ truncation, which is now reduced to 250 bytes.
427
640
 
428
- * Fix issue where `bootstrap.rb` overwrites the `level` of a `BroadcastLogger`'s `broadcasts`.
641
+ ```ruby
642
+ config.cache_store = :redis_cache_store, { max_key_size: 64 }
643
+ ```
644
+
645
+ *fatkodima*
646
+
647
+ * Use `UNLINK` command instead of `DEL` in `ActiveSupport::Cache::RedisCacheStore` for non-blocking deletion.
648
+
649
+ *Aron Roh*
650
+
651
+ * Add `Cache#read_counter` and `Cache#write_counter`
652
+
653
+ ```ruby
654
+ Rails.cache.write_counter("foo", 1)
655
+ Rails.cache.read_counter("foo") # => 1
656
+ Rails.cache.increment("foo")
657
+ Rails.cache.read_counter("foo") # => 2
658
+ ```
659
+
660
+ *Alex Ghiculescu*
661
+
662
+ * Introduce ActiveSupport::Testing::ErrorReporterAssertions#capture_error_reports
663
+
664
+ Captures all reported errors from within the block that match the given
665
+ error class.
666
+
667
+ ```ruby
668
+ reports = capture_error_reports(IOError) do
669
+ Rails.error.report(IOError.new("Oops"))
670
+ Rails.error.report(IOError.new("Oh no"))
671
+ Rails.error.report(StandardError.new)
672
+ end
673
+
674
+ assert_equal 2, reports.size
675
+ assert_equal "Oops", reports.first.error.message
676
+ assert_equal "Oh no", reports.last.error.message
677
+ ```
429
678
 
430
679
  *Andrew Novoselac*
431
680
 
432
- * Fix compatibility with the `semantic_logger` gem.
681
+ * Introduce ActiveSupport::ErrorReporter#add_middleware
682
+
683
+ When reporting an error, the error context middleware will be called with the reported error
684
+ and base execution context. The stack may mutate the context hash. The mutated context will
685
+ then be passed to error subscribers. Middleware receives the same parameters as `ErrorReporter#report`.
686
+
687
+ *Andrew Novoselac*, *Sam Schmidt*
688
+
689
+ * Change execution wrapping to report all exceptions, including `Exception`.
690
+
691
+ If a more serious error like `SystemStackError` or `NoMemoryError` happens,
692
+ the error reporter should be able to report these kinds of exceptions.
693
+
694
+ *Gannon McGibbon*
695
+
696
+ * `ActiveSupport::Testing::Parallelization.before_fork_hook` allows declaration of callbacks that
697
+ are invoked immediately before forking test workers.
698
+
699
+ *Mike Dalessio*
700
+
701
+ * Allow the `#freeze_time` testing helper to accept a date or time argument.
702
+
703
+ ```ruby
704
+ Time.current # => Sun, 09 Jul 2024 15:34:49 EST -05:00
705
+ freeze_time Time.current + 1.day
706
+ sleep 1
707
+ Time.current # => Mon, 10 Jul 2024 15:34:49 EST -05:00
708
+ ```
709
+
710
+ *Joshua Young*
711
+
712
+ * `ActiveSupport::JSON` now accepts options
713
+
714
+ It is now possible to pass options to `ActiveSupport::JSON`:
715
+ ```ruby
716
+ ActiveSupport::JSON.decode('{"key": "value"}', symbolize_names: true) # => { key: "value" }
717
+ ```
718
+
719
+ *matthaigh27*
720
+
721
+ * `ActiveSupport::Testing::NotificationAssertions`'s `assert_notification` now matches against payload subsets by default.
722
+
723
+ Previously the following assertion would fail due to excess key vals in the notification payload. Now with payload subset matching, it will pass.
724
+
725
+ ```ruby
726
+ assert_notification("post.submitted", title: "Cool Post") do
727
+ ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: "Cool Body")
728
+ end
729
+ ```
730
+
731
+ Additionally, you can now persist a matched notification for more customized assertions.
732
+
733
+ ```ruby
734
+ notification = assert_notification("post.submitted", title: "Cool Post") do
735
+ ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: Body.new("Cool Body"))
736
+ end
737
+
738
+ assert_instance_of(Body, notification.payload[:body])
739
+ ```
740
+
741
+ *Nicholas La Roux*
742
+
743
+ * Deprecate `String#mb_chars` and `ActiveSupport::Multibyte::Chars`.
744
+
745
+ These APIs are a relic of the Ruby 1.8 days when Ruby strings weren't encoding
746
+ aware. There is no legitimate reasons to need these APIs today.
747
+
748
+ *Jean Boussier*
749
+
750
+ * Deprecate `ActiveSupport::Configurable`
751
+
752
+ *Sean Doyle*
753
+
754
+ * `nil.to_query("key")` now returns `key`.
755
+
756
+ Previously it would return `key=`, preventing round tripping with `Rack::Utils.parse_nested_query`.
757
+
758
+ *Erol Fornoles*
759
+
760
+ * Avoid wrapping redis in a `ConnectionPool` when using `ActiveSupport::Cache::RedisCacheStore` if the `:redis`
761
+ option is already a `ConnectionPool`.
762
+
763
+ *Joshua Young*
764
+
765
+ * Alter `ERB::Util.tokenize` to return :PLAIN token with full input string when string doesn't contain ERB tags.
433
766
 
434
- The `semantic_logger` gem doesn't behave exactly like stdlib logger in that
435
- `SemanticLogger#level` returns a Symbol while stdlib `Logger#level` returns an Integer.
767
+ *Martin Emde*
436
768
 
437
- This caused the various `LogSubscriber` classes in Rails to break when assigned a
438
- `SemanticLogger` instance.
769
+ * Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceded by multibyte characters.
439
770
 
440
- *Jean Boussier*, *ojab*
771
+ *Martin Emde*
441
772
 
442
- * Fix MemoryStore to prevent race conditions when incrementing or decrementing.
773
+ * Add `ActiveSupport::Testing::NotificationAssertions` module to help with testing `ActiveSupport::Notifications`.
443
774
 
444
- *Pierre Jambet*
775
+ *Nicholas La Roux*, *Yishu See*, *Sean Doyle*
445
776
 
446
- * Implement `HashWithIndifferentAccess#to_proc`.
777
+ * `ActiveSupport::CurrentAttributes#attributes` now will return a new hash object on each call.
447
778
 
448
- Previously, calling `#to_proc` on `HashWithIndifferentAccess` object used inherited `#to_proc`
449
- method from the `Hash` class, which was not able to access values using indifferent keys.
779
+ Previously, the same hash object was returned each time that method was called.
450
780
 
451
781
  *fatkodima*
452
782
 
453
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activesupport/CHANGELOG.md) for previous changes.
783
+ * `ActiveSupport::JSON.encode` supports CIDR notation.
784
+
785
+ Previously:
786
+
787
+ ```ruby
788
+ ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0\""
789
+ ```
790
+
791
+ After this change:
792
+
793
+ ```ruby
794
+ ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0/24\""
795
+ ```
796
+
797
+ *Taketo Takashima*
798
+
799
+ * Make `ActiveSupport::FileUpdateChecker` faster when checking many file-extensions.
800
+
801
+ *Jonathan del Strother*
802
+
803
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activesupport/CHANGELOG.md) for previous changes.