activesupport 7.2.2.2 → 8.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +368 -152
  3. data/README.rdoc +1 -1
  4. data/lib/active_support/backtrace_cleaner.rb +73 -2
  5. data/lib/active_support/benchmark.rb +21 -0
  6. data/lib/active_support/benchmarkable.rb +3 -2
  7. data/lib/active_support/broadcast_logger.rb +61 -74
  8. data/lib/active_support/cache/file_store.rb +14 -4
  9. data/lib/active_support/cache/mem_cache_store.rb +27 -29
  10. data/lib/active_support/cache/memory_store.rb +11 -5
  11. data/lib/active_support/cache/null_store.rb +2 -2
  12. data/lib/active_support/cache/redis_cache_store.rb +43 -34
  13. data/lib/active_support/cache/strategy/local_cache.rb +72 -27
  14. data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
  15. data/lib/active_support/cache.rb +88 -20
  16. data/lib/active_support/callbacks.rb +28 -13
  17. data/lib/active_support/class_attribute.rb +33 -0
  18. data/lib/active_support/code_generator.rb +9 -0
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +8 -62
  20. data/lib/active_support/concurrency/share_lock.rb +0 -1
  21. data/lib/active_support/concurrency/thread_monitor.rb +55 -0
  22. data/lib/active_support/configurable.rb +34 -0
  23. data/lib/active_support/configuration_file.rb +15 -6
  24. data/lib/active_support/continuous_integration.rb +145 -0
  25. data/lib/active_support/core_ext/array/conversions.rb +3 -3
  26. data/lib/active_support/core_ext/array.rb +7 -7
  27. data/lib/active_support/core_ext/benchmark.rb +4 -14
  28. data/lib/active_support/core_ext/big_decimal.rb +1 -1
  29. data/lib/active_support/core_ext/class/attribute.rb +26 -20
  30. data/lib/active_support/core_ext/class.rb +2 -2
  31. data/lib/active_support/core_ext/date/conversions.rb +2 -0
  32. data/lib/active_support/core_ext/date.rb +5 -5
  33. data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -35
  34. data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
  35. data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
  36. data/lib/active_support/core_ext/date_time.rb +5 -5
  37. data/lib/active_support/core_ext/digest.rb +1 -1
  38. data/lib/active_support/core_ext/enumerable.rb +25 -8
  39. data/lib/active_support/core_ext/erb/util.rb +5 -5
  40. data/lib/active_support/core_ext/file.rb +1 -1
  41. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
  42. data/lib/active_support/core_ext/hash/except.rb +0 -12
  43. data/lib/active_support/core_ext/hash.rb +8 -8
  44. data/lib/active_support/core_ext/integer.rb +3 -3
  45. data/lib/active_support/core_ext/kernel.rb +3 -3
  46. data/lib/active_support/core_ext/module/attr_internal.rb +3 -4
  47. data/lib/active_support/core_ext/module/introspection.rb +3 -0
  48. data/lib/active_support/core_ext/module.rb +11 -11
  49. data/lib/active_support/core_ext/numeric.rb +3 -3
  50. data/lib/active_support/core_ext/object/json.rb +24 -11
  51. data/lib/active_support/core_ext/object/to_query.rb +7 -1
  52. data/lib/active_support/core_ext/object/try.rb +2 -2
  53. data/lib/active_support/core_ext/object.rb +13 -13
  54. data/lib/active_support/core_ext/pathname.rb +2 -2
  55. data/lib/active_support/core_ext/range/overlap.rb +3 -3
  56. data/lib/active_support/core_ext/range/sole.rb +17 -0
  57. data/lib/active_support/core_ext/range.rb +4 -4
  58. data/lib/active_support/core_ext/securerandom.rb +24 -8
  59. data/lib/active_support/core_ext/string/filters.rb +3 -3
  60. data/lib/active_support/core_ext/string/multibyte.rb +12 -3
  61. data/lib/active_support/core_ext/string/output_safety.rb +19 -12
  62. data/lib/active_support/core_ext/string.rb +13 -13
  63. data/lib/active_support/core_ext/symbol.rb +1 -1
  64. data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
  65. data/lib/active_support/core_ext/time/calculations.rb +7 -2
  66. data/lib/active_support/core_ext/time/compatibility.rb +2 -19
  67. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  68. data/lib/active_support/core_ext/time.rb +5 -5
  69. data/lib/active_support/core_ext.rb +1 -1
  70. data/lib/active_support/current_attributes/test_helper.rb +2 -2
  71. data/lib/active_support/current_attributes.rb +27 -17
  72. data/lib/active_support/delegation.rb +25 -44
  73. data/lib/active_support/dependencies/interlock.rb +11 -5
  74. data/lib/active_support/dependencies.rb +6 -2
  75. data/lib/active_support/deprecation/reporting.rb +4 -21
  76. data/lib/active_support/deprecation.rb +1 -1
  77. data/lib/active_support/duration.rb +14 -10
  78. data/lib/active_support/editor.rb +70 -0
  79. data/lib/active_support/encrypted_configuration.rb +20 -2
  80. data/lib/active_support/error_reporter.rb +81 -4
  81. data/lib/active_support/event_reporter/test_helper.rb +32 -0
  82. data/lib/active_support/event_reporter.rb +592 -0
  83. data/lib/active_support/evented_file_update_checker.rb +5 -2
  84. data/lib/active_support/execution_context.rb +64 -7
  85. data/lib/active_support/execution_wrapper.rb +1 -1
  86. data/lib/active_support/file_update_checker.rb +8 -6
  87. data/lib/active_support/gem_version.rb +3 -3
  88. data/lib/active_support/gzip.rb +1 -0
  89. data/lib/active_support/hash_with_indifferent_access.rb +61 -38
  90. data/lib/active_support/i18n_railtie.rb +19 -11
  91. data/lib/active_support/inflector/inflections.rb +32 -15
  92. data/lib/active_support/inflector/methods.rb +2 -2
  93. data/lib/active_support/inflector/transliterate.rb +6 -8
  94. data/lib/active_support/isolated_execution_state.rb +17 -17
  95. data/lib/active_support/json/decoding.rb +6 -4
  96. data/lib/active_support/json/encoding.rb +157 -21
  97. data/lib/active_support/lazy_load_hooks.rb +1 -1
  98. data/lib/active_support/log_subscriber.rb +2 -6
  99. data/lib/active_support/logger_thread_safe_level.rb +6 -3
  100. data/lib/active_support/message_encryptors.rb +54 -2
  101. data/lib/active_support/message_pack/extensions.rb +6 -1
  102. data/lib/active_support/message_verifier.rb +9 -0
  103. data/lib/active_support/message_verifiers.rb +57 -3
  104. data/lib/active_support/messages/rotation_coordinator.rb +9 -0
  105. data/lib/active_support/messages/rotator.rb +10 -0
  106. data/lib/active_support/multibyte/chars.rb +12 -2
  107. data/lib/active_support/multibyte.rb +4 -0
  108. data/lib/active_support/notifications/fanout.rb +64 -43
  109. data/lib/active_support/notifications/instrumenter.rb +1 -1
  110. data/lib/active_support/number_helper.rb +22 -0
  111. data/lib/active_support/railtie.rb +32 -9
  112. data/lib/active_support/structured_event_subscriber.rb +99 -0
  113. data/lib/active_support/subscriber.rb +0 -5
  114. data/lib/active_support/syntax_error_proxy.rb +7 -0
  115. data/lib/active_support/tagged_logging.rb +5 -0
  116. data/lib/active_support/test_case.rb +67 -6
  117. data/lib/active_support/testing/assertions.rb +115 -27
  118. data/lib/active_support/testing/autorun.rb +5 -0
  119. data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
  120. data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
  121. data/lib/active_support/testing/isolation.rb +0 -2
  122. data/lib/active_support/testing/notification_assertions.rb +92 -0
  123. data/lib/active_support/testing/parallelization/server.rb +15 -2
  124. data/lib/active_support/testing/parallelization/worker.rb +8 -4
  125. data/lib/active_support/testing/parallelization.rb +25 -1
  126. data/lib/active_support/testing/tests_without_assertions.rb +1 -1
  127. data/lib/active_support/testing/time_helpers.rb +9 -4
  128. data/lib/active_support/time_with_zone.rb +36 -23
  129. data/lib/active_support/values/time_zone.rb +19 -10
  130. data/lib/active_support/xml_mini.rb +3 -2
  131. data/lib/active_support.rb +21 -9
  132. metadata +34 -12
  133. data/lib/active_support/core_ext/range/each.rb +0 -24
  134. data/lib/active_support/proxy_object.rb +0 -20
  135. data/lib/active_support/testing/strict_warnings.rb +0 -43
data/CHANGELOG.md CHANGED
@@ -1,289 +1,505 @@
1
- ## Rails 7.2.2.2 (August 13, 2025) ##
1
+ ## Rails 8.1.2 (January 08, 2026) ##
2
2
 
3
- * No changes.
3
+ * Make `delegate` and `delegate_missing_to` work in BasicObject subclasses.
4
4
 
5
+ *Rafael Mendonça França*
5
6
 
6
- ## Rails 7.2.2.1 (December 10, 2024) ##
7
+ * Fix Inflectors when using a locale that fallbacks to `:en`.
7
8
 
8
- * No changes.
9
+ *Said Kaldybaev*
9
10
 
11
+ * Fix `ActiveSupport::TimeWithZone#as_json` to consistently return UTF-8 strings.
10
12
 
11
- ## Rails 7.2.2 (October 30, 2024) ##
13
+ Previously the returned string would sometime be encoded in US-ASCII, which in
14
+ some cases may be problematic.
12
15
 
13
- * Include options when instrumenting `ActiveSupport::Cache::Store#delete` and `ActiveSupport::Cache::Store#delete_multi`.
16
+ Now the method consistently always return UTF-8 strings.
14
17
 
15
- *Adam Renberg Tamm*
18
+ *Jean Boussier*
16
19
 
17
- * Print test names when running `rails test -v` for parallel tests.
20
+ * Fix `TimeWithZone#xmlschema` when wrapping a `DateTime` instance in local time.
18
21
 
19
- *John Hawthorn*, *Abeid Ahmed*
22
+ Previously it would return an invalid time.
20
23
 
24
+ *Dmytro Rymar*
21
25
 
22
- ## Rails 7.2.1.2 (October 23, 2024) ##
26
+ * Implement LocalCache strategy on `ActiveSupport::Cache::MemoryStore`. The memory store
27
+ needs to respond to the same interface as other cache stores (e.g. `ActiveSupport::NullStore`).
23
28
 
24
- * No changes.
29
+ *Mikey Gough*
25
30
 
31
+ * Fix `ActiveSupport::Inflector.humanize` with international characters.
26
32
 
27
- ## Rails 7.2.1.1 (October 15, 2024) ##
33
+ ```ruby
34
+ ActiveSupport::Inflector.humanize("áÉÍÓÚ") # => "Áéíóú"
35
+ ActiveSupport::Inflector.humanize("аБВГДЕ") # => "Абвгде"
36
+ ```
28
37
 
29
- * No changes.
38
+ *Jose Luis Duran*
30
39
 
31
40
 
32
- ## Rails 7.2.1 (August 22, 2024) ##
41
+ ## Rails 8.1.1 (October 28, 2025) ##
33
42
 
34
43
  * No changes.
35
44
 
36
45
 
37
- ## Rails 7.2.0 (August 09, 2024) ##
46
+ ## Rails 8.1.0 (October 22, 2025) ##
38
47
 
39
- * Fix `delegate_missing_to allow_nil: true` when called with implict self
48
+ * Remove deprecated passing a Time object to `Time#since`.
49
+
50
+ *Rafael Mendonça França*
51
+
52
+ * Remove deprecated `Benchmark.ms` method. It is now defined in the `benchmark` gem.
53
+
54
+ *Rafael Mendonça França*
55
+
56
+ * Remove deprecated addition for `Time` instances with `ActiveSupport::TimeWithZone`.
57
+
58
+ *Rafael Mendonça França*
59
+
60
+ * Remove deprecated support for `to_time` to preserve the system local time. It will now always preserve the receiver
61
+ timezone.
62
+
63
+ *Rafael Mendonça França*
64
+
65
+ * Deprecate `config.active_support.to_time_preserves_timezone`.
66
+
67
+ *Rafael Mendonça França*
68
+
69
+ * Standardize event name formatting in `assert_event_reported` error messages.
70
+
71
+ The event name in failure messages now uses `.inspect` (e.g., `name: "user.created"`)
72
+ to match `assert_events_reported` and provide type clarity between strings and symbols.
73
+ This only affects tests that assert on the failure message format itself.
74
+
75
+ *George Ma*
76
+
77
+ * Fix `Enumerable#sole` to return the full tuple instead of just the first element of the tuple.
78
+
79
+ *Olivier Bellone*
80
+
81
+ * Fix parallel tests hanging when worker processes die abruptly.
82
+
83
+ Previously, if a worker process was killed (e.g., OOM killed, `kill -9`) during parallel
84
+ test execution, the test suite would hang forever waiting for the dead worker.
85
+
86
+ *Joshua Young*
87
+
88
+ * Add `config.active_support.escape_js_separators_in_json`.
89
+
90
+ Introduce a new framework default to skip escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON.
91
+
92
+ Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019.
93
+ As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset.
94
+
95
+ *Étienne Barrié*, *Jean Boussier*
96
+
97
+ * Fix `NameError` when `class_attribute` is defined on instance singleton classes.
98
+
99
+ Previously, calling `class_attribute` on an instance's singleton class would raise
100
+ a `NameError` when accessing the attribute through the instance.
40
101
 
41
102
  ```ruby
42
- class Person
43
- delegate_missing_to :address, allow_nil: true
103
+ object = MyClass.new
104
+ object.singleton_class.class_attribute :foo, default: "bar"
105
+ object.foo # previously raised NameError, now returns "bar"
106
+ ```
44
107
 
45
- def address
46
- nil
47
- end
108
+ *Joshua Young*
109
+
110
+ * Introduce `ActiveSupport::Testing::EventReporterAssertions#with_debug_event_reporting`
111
+ to enable event reporter debug mode in tests.
112
+
113
+ The previous way to enable debug mode is by using `#with_debug` on the
114
+ event reporter itself, which is too verbose. This new helper will help
115
+ clear up any confusion on how to test debug events.
116
+
117
+ *Gannon McGibbon*
118
+
119
+ * Add `ActiveSupport::StructuredEventSubscriber` for consuming notifications and
120
+ emitting structured event logs. Events may be emitted with the `#emit_event`
121
+ or `#emit_debug_event` methods.
48
122
 
49
- def berliner?
50
- city == "Berlin"
123
+ ```ruby
124
+ class MyStructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber
125
+ def notification(event)
126
+ emit_event("my.notification", data: 1)
51
127
  end
52
128
  end
129
+ ```
130
+
131
+ *Adrianna Chang*
132
+
133
+ * `ActiveSupport::FileUpdateChecker` does not depend on `Time.now` to prevent unecessary reloads with time travel test helpers
134
+
135
+ *Jan Grodowski*
136
+
137
+ * Add `ActiveSupport::Cache::Store#namespace=` and `#namespace`.
138
+
139
+ Can be used as an alternative to `Store#clear` in some situations such as parallel
140
+ testing.
141
+
142
+ *Nick Schwaderer*
143
+
144
+ * Create `parallel_worker_id` helper for running parallel tests. This allows users to
145
+ know which worker they are currently running in.
146
+
147
+ *Nick Schwaderer*
148
+
149
+ * Make the cache of `ActiveSupport::Cache::Strategy::LocalCache::Middleware` updatable.
150
+
151
+ If the cache client at `Rails.cache` of a booted application changes, the corresponding
152
+ mounted middleware needs to update in order for request-local caches to be setup properly.
153
+ Otherwise, redundant cache operations will erroneously hit the datastore.
154
+
155
+ *Gannon McGibbon*
53
156
 
54
- Person.new.city # => nil
55
- Person.new.berliner? # undefined local variable or method `city' for an instance of Person (NameError)
157
+ * Add `assert_events_reported` test helper for `ActiveSupport::EventReporter`.
158
+
159
+ This new assertion allows testing multiple events in a single block, regardless of order:
160
+
161
+ ```ruby
162
+ assert_events_reported([
163
+ { name: "user.created", payload: { id: 123 } },
164
+ { name: "email.sent", payload: { to: "user@example.com" } }
165
+ ]) do
166
+ create_user_and_send_welcome_email
167
+ end
56
168
  ```
57
169
 
58
- *Jean Boussier*
170
+ *George Ma*
59
171
 
60
- * Add `logger` as a dependency since it is a bundled gem candidate for Ruby 3.5
172
+ * Add `ActiveSupport::TimeZone#standard_name` method.
61
173
 
62
- *Earlopain*
174
+ ``` ruby
175
+ zone = ActiveSupport::TimeZone['Hawaii']
176
+ # Old way
177
+ ActiveSupport::TimeZone::MAPPING[zone.name]
178
+ # New way
179
+ zone.standard_name # => 'Pacific/Honolulu'
180
+ ```
63
181
 
64
- * Define `Digest::UUID.nil_uuid`, which returns the so-called nil UUID.
182
+ *Bogdan Gusiev*
65
183
 
66
- *Xavier Noria*
184
+ * Add Structured Event Reporter, accessible via `Rails.event`.
67
185
 
68
- * Support `duration` type in `ActiveSupport::XmlMini`.
186
+ The Event Reporter provides a unified interface for producing structured events in Rails
187
+ applications:
69
188
 
70
- *heka1024*
189
+ ```ruby
190
+ Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
191
+ ```
71
192
 
72
- * Remove deprecated `ActiveSupport::Notifications::Event#children` and `ActiveSupport::Notifications::Event#parent_of?`.
193
+ It supports adding tags to events:
73
194
 
74
- *Rafael Mendonça França*
195
+ ```ruby
196
+ Rails.event.tagged("graphql") do
197
+ # Event includes tags: { graphql: true }
198
+ Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
199
+ end
200
+ ```
75
201
 
76
- * Remove deprecated support to call the following methods without passing a deprecator:
202
+ As well as context:
203
+ ```ruby
204
+ # All events will contain context: {request_id: "abc123", shop_id: 456}
205
+ Rails.event.set_context(request_id: "abc123", shop_id: 456)
206
+ ```
77
207
 
78
- - `deprecate`
79
- - `deprecate_constant`
80
- - `ActiveSupport::Deprecation::DeprecatedObjectProxy.new`
81
- - `ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new`
82
- - `ActiveSupport::Deprecation::DeprecatedConstantProxy.new`
83
- - `assert_deprecated`
84
- - `assert_not_deprecated`
85
- - `collect_deprecations`
208
+ Events are emitted to subscribers. Applications register subscribers to
209
+ control how events are serialized and emitted. Subscribers must implement
210
+ an `#emit` method, which receives the event hash:
86
211
 
87
- *Rafael Mendonça França*
212
+ ```ruby
213
+ class LogSubscriber
214
+ def emit(event)
215
+ payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ")
216
+ source_location = event[:source_location]
217
+ log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}"
218
+ Rails.logger.info(log)
219
+ end
220
+ end
221
+ ```
88
222
 
89
- * Remove deprecated `ActiveSupport::Deprecation` delegation to instance.
223
+ *Adrianna Chang*
90
224
 
91
- *Rafael Mendonça França*
225
+ * Make `ActiveSupport::Logger` `#freeze`-friendly.
92
226
 
93
- * Remove deprecated `SafeBuffer#clone_empty`.
227
+ *Joshua Young*
94
228
 
95
- *Rafael Mendonça França*
229
+ * Make `ActiveSupport::Gzip.compress` deterministic based on input.
96
230
 
97
- * Remove deprecated `#to_default_s` from `Array`, `Date`, `DateTime` and `Time`.
231
+ `ActiveSupport::Gzip.compress` used to include a timestamp in the output,
232
+ causing consecutive calls with the same input data to have different output
233
+ if called during different seconds. It now always sets the timestamp to `0`
234
+ so that the output is identical for any given input.
98
235
 
99
- *Rafael Mendonça França*
236
+ *Rob Brackett*
100
237
 
101
- * Remove deprecated support to passing `Dalli::Client` instances to `MemCacheStore`.
238
+ * Given an array of `Thread::Backtrace::Location` objects, the new method
239
+ `ActiveSupport::BacktraceCleaner#clean_locations` returns an array with the
240
+ clean ones:
102
241
 
103
- *Rafael Mendonça França*
242
+ ```ruby
243
+ clean_locations = backtrace_cleaner.clean_locations(caller_locations)
244
+ ```
104
245
 
105
- * Remove deprecated `config.active_support.use_rfc4122_namespaced_uuids`.
246
+ Filters and silencers receive strings as usual. However, the `path`
247
+ attributes of the locations in the returned array are the original,
248
+ unfiltered ones, since locations are immutable.
106
249
 
107
- *Rafael Mendonça França*
250
+ *Xavier Noria*
108
251
 
109
- * Remove deprecated `config.active_support.remove_deprecated_time_with_zone_name`.
252
+ * Improve `CurrentAttributes` and `ExecutionContext` state managment in test cases.
110
253
 
111
- *Rafael Mendonça França*
254
+ Previously these two global state would be entirely cleared out whenever calling
255
+ into code that is wrapped by the Rails executor, typically Action Controller or
256
+ Active Job helpers:
112
257
 
113
- * Remove deprecated `config.active_support.disable_to_s_conversion`.
258
+ ```ruby
259
+ test "#index works" do
260
+ CurrentUser.id = 42
261
+ get :index
262
+ CurrentUser.id == nil
263
+ end
264
+ ```
114
265
 
115
- *Rafael Mendonça França*
266
+ Now re-entering the executor properly save and restore that state.
116
267
 
117
- * Remove deprecated support to bolding log text with positional boolean in `ActiveSupport::LogSubscriber#color`.
268
+ *Jean Boussier*
118
269
 
119
- *Rafael Mendonça França*
270
+ * The new method `ActiveSupport::BacktraceCleaner#first_clean_location`
271
+ returns the first clean location of the caller's call stack, or `nil`.
272
+ Locations are `Thread::Backtrace::Location` objects. Useful when you want to
273
+ report the application-level location where something happened as an object.
120
274
 
121
- * Remove deprecated constants `ActiveSupport::LogSubscriber::CLEAR` and `ActiveSupport::LogSubscriber::BOLD`.
275
+ *Xavier Noria*
122
276
 
123
- *Rafael Mendonça França*
277
+ * FileUpdateChecker and EventedFileUpdateChecker ignore changes in Gem.path now.
124
278
 
125
- * Remove deprecated support for `config.active_support.cache_format_version = 6.1`.
279
+ *Ermolaev Andrey*, *zzak*
126
280
 
127
- *Rafael Mendonça França*
281
+ * The new method `ActiveSupport::BacktraceCleaner#first_clean_frame` returns
282
+ the first clean frame of the caller's backtrace, or `nil`. Useful when you
283
+ want to report the application-level frame where something happened as a
284
+ string.
128
285
 
129
- * Remove deprecated `:pool_size` and `:pool_timeout` options for the cache storage.
286
+ *Xavier Noria*
130
287
 
131
- *Rafael Mendonça França*
288
+ * Always clear `CurrentAttributes` instances.
132
289
 
133
- * Warn on tests without assertions.
290
+ Previously `CurrentAttributes` instance would be reset at the end of requests.
291
+ Meaning its attributes would be re-initialized.
134
292
 
135
- `ActiveSupport::TestCase` now warns when tests do not run any assertions.
136
- This is helpful in detecting broken tests that do not perform intended assertions.
293
+ This is problematic because it assume these objects don't hold any state
294
+ other than their declared attribute, which isn't always the case, and
295
+ can lead to state leak across request.
137
296
 
138
- *fatkodima*
297
+ Now `CurrentAttributes` instances are abandoned at the end of a request,
298
+ and a new instance is created at the start of the next request.
139
299
 
140
- * Support `hexBinary` type in `ActiveSupport::XmlMini`.
300
+ *Jean Boussier*, *Janko Marohnić*
141
301
 
142
- *heka1024*
302
+ * Add public API for `before_fork_hook` in parallel testing.
143
303
 
144
- * Deprecate `ActiveSupport::ProxyObject` in favor of Ruby's built-in `BasicObject`.
304
+ Introduces a public API for calling the before fork hooks implemented by parallel testing.
145
305
 
146
- *Earlopain*
306
+ ```ruby
307
+ parallelize_before_fork do
308
+ # perform an action before test processes are forked
309
+ end
310
+ ```
147
311
 
148
- * `stub_const` now accepts a `exists: false` parameter to allow stubbing missing constants.
312
+ *Eileen M. Uchitelle*
149
313
 
150
- *Jean Boussier*
314
+ * Implement ability to skip creating parallel testing databases.
151
315
 
152
- * Make `ActiveSupport::BacktraceCleaner` copy filters and silencers on dup and clone.
316
+ With parallel testing, Rails will create a database per process. If this isn't
317
+ desirable or you would like to implement databases handling on your own, you can
318
+ now turn off this default behavior.
153
319
 
154
- Previously the copy would still share the internal silencers and filters array,
155
- causing state to leak.
320
+ To skip creating a database per process, you can change it via the
321
+ `parallelize` method:
156
322
 
157
- *Jean Boussier*
323
+ ```ruby
324
+ parallelize(workers: 10, parallelize_databases: false)
325
+ ```
326
+
327
+ or via the application configuration:
158
328
 
159
- * Updating Astana with Western Kazakhstan TZInfo identifier.
329
+ ```ruby
330
+ config.active_support.parallelize_databases = false
331
+ ```
160
332
 
161
- *Damian Nelson*
333
+ *Eileen M. Uchitelle*
162
334
 
163
- * Add filename support for `ActiveSupport::Logger.logger_outputs_to?`.
335
+ * Allow to configure maximum cache key sizes
336
+
337
+ When the key exceeds the configured limit (250 bytes by default), it will be truncated and
338
+ the digest of the rest of the key appended to it.
339
+
340
+ Note that previously `ActiveSupport::Cache::RedisCacheStore` allowed up to 1kb cache keys before
341
+ truncation, which is now reduced to 250 bytes.
164
342
 
165
343
  ```ruby
166
- logger = Logger.new('/var/log/rails.log')
167
- ActiveSupport::Logger.logger_outputs_to?(logger, '/var/log/rails.log')
344
+ config.cache_store = :redis_cache_store, { max_key_size: 64 }
168
345
  ```
169
346
 
170
- *Christian Schmidt*
347
+ *fatkodima*
171
348
 
172
- * Include `IPAddr#prefix` when serializing an `IPAddr` using the
173
- `ActiveSupport::MessagePack` serializer.
349
+ * Use `UNLINK` command instead of `DEL` in `ActiveSupport::Cache::RedisCacheStore` for non-blocking deletion.
174
350
 
175
- This change is backward and forward compatible — old payloads can
176
- still be read, and new payloads will be readable by older versions of Rails.
351
+ *Aron Roh*
177
352
 
178
- *Taiki Komaba*
353
+ * Add `Cache#read_counter` and `Cache#write_counter`
179
354
 
180
- * Add `default:` support for `ActiveSupport::CurrentAttributes.attribute`.
355
+ ```ruby
356
+ Rails.cache.write_counter("foo", 1)
357
+ Rails.cache.read_counter("foo") # => 1
358
+ Rails.cache.increment("foo")
359
+ Rails.cache.read_counter("foo") # => 2
360
+ ```
361
+
362
+ *Alex Ghiculescu*
363
+
364
+ * Introduce ActiveSupport::Testing::ErrorReporterAssertions#capture_error_reports
365
+
366
+ Captures all reported errors from within the block that match the given
367
+ error class.
181
368
 
182
369
  ```ruby
183
- class Current < ActiveSupport::CurrentAttributes
184
- attribute :counter, default: 0
370
+ reports = capture_error_reports(IOError) do
371
+ Rails.error.report(IOError.new("Oops"))
372
+ Rails.error.report(IOError.new("Oh no"))
373
+ Rails.error.report(StandardError.new)
185
374
  end
375
+
376
+ assert_equal 2, reports.size
377
+ assert_equal "Oops", reports.first.error.message
378
+ assert_equal "Oh no", reports.last.error.message
186
379
  ```
187
380
 
188
- *Sean Doyle*
381
+ *Andrew Novoselac*
382
+
383
+ * Introduce ActiveSupport::ErrorReporter#add_middleware
384
+
385
+ When reporting an error, the error context middleware will be called with the reported error
386
+ and base execution context. The stack may mutate the context hash. The mutated context will
387
+ then be passed to error subscribers. Middleware receives the same parameters as `ErrorReporter#report`.
189
388
 
190
- * Yield instance to `Object#with` block.
389
+ *Andrew Novoselac*, *Sam Schmidt*
390
+
391
+ * Change execution wrapping to report all exceptions, including `Exception`.
392
+
393
+ If a more serious error like `SystemStackError` or `NoMemoryError` happens,
394
+ the error reporter should be able to report these kinds of exceptions.
395
+
396
+ *Gannon McGibbon*
397
+
398
+ * `ActiveSupport::Testing::Parallelization.before_fork_hook` allows declaration of callbacks that
399
+ are invoked immediately before forking test workers.
400
+
401
+ *Mike Dalessio*
402
+
403
+ * Allow the `#freeze_time` testing helper to accept a date or time argument.
191
404
 
192
405
  ```ruby
193
- client.with(timeout: 5_000) do |c|
194
- c.get("/commits")
195
- end
406
+ Time.current # => Sun, 09 Jul 2024 15:34:49 EST -05:00
407
+ freeze_time Time.current + 1.day
408
+ sleep 1
409
+ Time.current # => Mon, 10 Jul 2024 15:34:49 EST -05:00
196
410
  ```
197
411
 
198
- *Sean Doyle*
412
+ *Joshua Young*
199
413
 
200
- * Use logical core count instead of physical core count to determine the
201
- default number of workers when parallelizing tests.
414
+ * `ActiveSupport::JSON` now accepts options
202
415
 
203
- *Jonathan Hefner*
416
+ It is now possible to pass options to `ActiveSupport::JSON`:
417
+ ```ruby
418
+ ActiveSupport::JSON.decode('{"key": "value"}', symbolize_names: true) # => { key: "value" }
419
+ ```
204
420
 
205
- * Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
421
+ *matthaigh27*
206
422
 
207
- There is a bug in the current implementation of #travel_to:
208
- it remembers a timezone of its argument, and all stubbed methods start
209
- returning results in that remembered timezone. However, the expected
210
- behavior is to return results in a system timezone.
423
+ * `ActiveSupport::Testing::NotificationAssertions`'s `assert_notification` now matches against payload subsets by default.
211
424
 
212
- *Aleksei Chernenkov*
425
+ Previously the following assertion would fail due to excess key vals in the notification payload. Now with payload subset matching, it will pass.
213
426
 
214
- * Add `ErrorReported#unexpected` to report precondition violations.
427
+ ```ruby
428
+ assert_notification("post.submitted", title: "Cool Post") do
429
+ ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: "Cool Body")
430
+ end
431
+ ```
215
432
 
216
- For example:
433
+ Additionally, you can now persist a matched notification for more customized assertions.
217
434
 
218
435
  ```ruby
219
- def edit
220
- if published?
221
- Rails.error.unexpected("[BUG] Attempting to edit a published article, that shouldn't be possible")
222
- return false
223
- end
224
- # ...
436
+ notification = assert_notification("post.submitted", title: "Cool Post") do
437
+ ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: Body.new("Cool Body"))
225
438
  end
439
+
440
+ assert_instance_of(Body, notification.payload[:body])
226
441
  ```
227
442
 
228
- The above will raise an error in development and test, but only report the error in production.
443
+ *Nicholas La Roux*
229
444
 
230
- *Jean Boussier*
445
+ * Deprecate `String#mb_chars` and `ActiveSupport::Multibyte::Chars`.
231
446
 
232
- * Make the order of read_multi and write_multi notifications for `Cache::Store#fetch_multi` operations match the order they are executed in.
447
+ These APIs are a relic of the Ruby 1.8 days when Ruby strings weren't encoding
448
+ aware. There is no legitimate reasons to need these APIs today.
449
+
450
+ *Jean Boussier*
233
451
 
234
- *Adam Renberg Tamm*
452
+ * Deprecate `ActiveSupport::Configurable`
235
453
 
236
- * Make return values of `Cache::Store#write` consistent.
454
+ *Sean Doyle*
237
455
 
238
- The return value was not specified before. Now it returns `true` on a successful write,
239
- `nil` if there was an error talking to the cache backend, and `false` if the write failed
240
- for another reason (e.g. the key already exists and `unless_exist: true` was passed).
456
+ * `nil.to_query("key")` now returns `key`.
241
457
 
242
- *Sander Verdonschot*
458
+ Previously it would return `key=`, preventing round tripping with `Rack::Utils.parse_nested_query`.
243
459
 
244
- * Fix logged cache keys not always matching actual key used by cache action.
460
+ *Erol Fornoles*
245
461
 
246
- *Hartley McGuire*
462
+ * Avoid wrapping redis in a `ConnectionPool` when using `ActiveSupport::Cache::RedisCacheStore` if the `:redis`
463
+ option is already a `ConnectionPool`.
247
464
 
248
- * Improve error messages of `assert_changes` and `assert_no_changes`.
465
+ *Joshua Young*
249
466
 
250
- `assert_changes` error messages now display objects with `.inspect` to make it easier
251
- to differentiate nil from empty strings, strings from symbols, etc.
252
- `assert_no_changes` error messages now surface the actual value.
467
+ * Alter `ERB::Util.tokenize` to return :PLAIN token with full input string when string doesn't contain ERB tags.
253
468
 
254
- *pcreux*
469
+ *Martin Emde*
255
470
 
256
- * Fix `#to_fs(:human_size)` to correctly work with negative numbers.
471
+ * Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceded by multibyte characters.
257
472
 
258
- *Earlopain*
473
+ *Martin Emde*
259
474
 
260
- * Fix `BroadcastLogger#dup` so that it duplicates the logger's `broadcasts`.
475
+ * Add `ActiveSupport::Testing::NotificationAssertions` module to help with testing `ActiveSupport::Notifications`.
261
476
 
262
- *Andrew Novoselac*
477
+ *Nicholas La Roux*, *Yishu See*, *Sean Doyle*
263
478
 
264
- * Fix issue where `bootstrap.rb` overwrites the `level` of a `BroadcastLogger`'s `broadcasts`.
479
+ * `ActiveSupport::CurrentAttributes#attributes` now will return a new hash object on each call.
265
480
 
266
- *Andrew Novoselac*
481
+ Previously, the same hash object was returned each time that method was called.
267
482
 
268
- * Fix compatibility with the `semantic_logger` gem.
483
+ *fatkodima*
269
484
 
270
- The `semantic_logger` gem doesn't behave exactly like stdlib logger in that
271
- `SemanticLogger#level` returns a Symbol while stdlib `Logger#level` returns an Integer.
485
+ * `ActiveSupport::JSON.encode` supports CIDR notation.
272
486
 
273
- This caused the various `LogSubscriber` classes in Rails to break when assigned a
274
- `SemanticLogger` instance.
487
+ Previously:
275
488
 
276
- *Jean Boussier*, *ojab*
489
+ ```ruby
490
+ ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0\""
491
+ ```
277
492
 
278
- * Fix MemoryStore to prevent race conditions when incrementing or decrementing.
493
+ After this change:
279
494
 
280
- *Pierre Jambet*
495
+ ```ruby
496
+ ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0/24\""
497
+ ```
281
498
 
282
- * Implement `HashWithIndifferentAccess#to_proc`.
499
+ *Taketo Takashima*
283
500
 
284
- Previously, calling `#to_proc` on `HashWithIndifferentAccess` object used inherited `#to_proc`
285
- method from the `Hash` class, which was not able to access values using indifferent keys.
501
+ * Make `ActiveSupport::FileUpdateChecker` faster when checking many file-extensions.
286
502
 
287
- *fatkodima*
503
+ *Jonathan del Strother*
288
504
 
289
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activesupport/CHANGELOG.md) for previous changes.
505
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activesupport/CHANGELOG.md) for previous changes.