activesupport 8.0.2.1 → 8.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +247 -136
  3. data/README.rdoc +1 -1
  4. data/lib/active_support/backtrace_cleaner.rb +71 -0
  5. data/lib/active_support/broadcast_logger.rb +46 -59
  6. data/lib/active_support/cache/mem_cache_store.rb +25 -27
  7. data/lib/active_support/cache/redis_cache_store.rb +36 -30
  8. data/lib/active_support/cache/strategy/local_cache.rb +16 -7
  9. data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
  10. data/lib/active_support/cache.rb +70 -6
  11. data/lib/active_support/configurable.rb +28 -0
  12. data/lib/active_support/continuous_integration.rb +145 -0
  13. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  14. data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
  15. data/lib/active_support/core_ext/enumerable.rb +16 -4
  16. data/lib/active_support/core_ext/erb/util.rb +3 -3
  17. data/lib/active_support/core_ext/object/json.rb +8 -1
  18. data/lib/active_support/core_ext/object/to_query.rb +7 -1
  19. data/lib/active_support/core_ext/object/try.rb +2 -2
  20. data/lib/active_support/core_ext/range/overlap.rb +3 -3
  21. data/lib/active_support/core_ext/range/sole.rb +17 -0
  22. data/lib/active_support/core_ext/range.rb +1 -1
  23. data/lib/active_support/core_ext/string/filters.rb +3 -3
  24. data/lib/active_support/core_ext/string/multibyte.rb +12 -3
  25. data/lib/active_support/core_ext/string/output_safety.rb +19 -12
  26. data/lib/active_support/current_attributes/test_helper.rb +2 -2
  27. data/lib/active_support/current_attributes.rb +26 -16
  28. data/lib/active_support/deprecation/reporting.rb +4 -2
  29. data/lib/active_support/deprecation.rb +1 -1
  30. data/lib/active_support/editor.rb +70 -0
  31. data/lib/active_support/error_reporter.rb +50 -6
  32. data/lib/active_support/event_reporter/test_helper.rb +32 -0
  33. data/lib/active_support/event_reporter.rb +570 -0
  34. data/lib/active_support/evented_file_update_checker.rb +5 -1
  35. data/lib/active_support/execution_context.rb +64 -7
  36. data/lib/active_support/file_update_checker.rb +7 -5
  37. data/lib/active_support/gem_version.rb +3 -3
  38. data/lib/active_support/gzip.rb +1 -0
  39. data/lib/active_support/hash_with_indifferent_access.rb +47 -24
  40. data/lib/active_support/i18n_railtie.rb +1 -2
  41. data/lib/active_support/inflector/inflections.rb +31 -15
  42. data/lib/active_support/inflector/transliterate.rb +6 -8
  43. data/lib/active_support/isolated_execution_state.rb +7 -13
  44. data/lib/active_support/json/decoding.rb +6 -4
  45. data/lib/active_support/json/encoding.rb +103 -14
  46. data/lib/active_support/lazy_load_hooks.rb +1 -1
  47. data/lib/active_support/log_subscriber.rb +2 -0
  48. data/lib/active_support/logger_thread_safe_level.rb +6 -3
  49. data/lib/active_support/message_encryptors.rb +52 -0
  50. data/lib/active_support/message_pack/extensions.rb +5 -0
  51. data/lib/active_support/message_verifiers.rb +52 -0
  52. data/lib/active_support/messages/rotation_coordinator.rb +9 -0
  53. data/lib/active_support/messages/rotator.rb +5 -0
  54. data/lib/active_support/multibyte/chars.rb +8 -1
  55. data/lib/active_support/multibyte.rb +4 -0
  56. data/lib/active_support/railtie.rb +26 -12
  57. data/lib/active_support/syntax_error_proxy.rb +3 -0
  58. data/lib/active_support/test_case.rb +61 -6
  59. data/lib/active_support/testing/assertions.rb +34 -6
  60. data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
  61. data/lib/active_support/testing/event_reporter_assertions.rb +217 -0
  62. data/lib/active_support/testing/notification_assertions.rb +92 -0
  63. data/lib/active_support/testing/parallelization/worker.rb +2 -0
  64. data/lib/active_support/testing/parallelization.rb +13 -0
  65. data/lib/active_support/testing/tests_without_assertions.rb +1 -1
  66. data/lib/active_support/testing/time_helpers.rb +7 -3
  67. data/lib/active_support/time_with_zone.rb +19 -5
  68. data/lib/active_support/values/time_zone.rb +8 -1
  69. data/lib/active_support/xml_mini.rb +1 -2
  70. data/lib/active_support.rb +11 -0
  71. metadata +11 -5
  72. data/lib/active_support/core_ext/range/each.rb +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51325bdd043f3ecb40d38809265f43b19559bea29ca3d72402fb421e25be1653
4
- data.tar.gz: 81ac7af00f2f59da740adb21e77528f653dd0149120dfc0bc163b77eacb500ef
3
+ metadata.gz: 961314ec0e1413ca082492acda67d57e19e5011d13725707c3b3d83cb3e88b6c
4
+ data.tar.gz: '0918a0dcb857f0621acf8c0034cc568efceddbaf92991da1d73ea1a3ae892f40'
5
5
  SHA512:
6
- metadata.gz: abf1f60ae3cfa4e2fb533a4583f2c310e43801e783983b7908913243ddd065ae45f44a4eeffe41fec82ab553097ff5c5c8d9c413580b577c3e1181a8255f5737
7
- data.tar.gz: 1effa0559c4730a836774d42fb9b871ebdd95f25161988fa9afd7b30700debbf48d1f705d8434a40b032e2a772bca7ad4e3351f7cb64b48ff912843fcdc43ecf
6
+ metadata.gz: d167935a467f95a7dd138a7498328e7f8bb5970ad79e33ea43267fe79d6a40f5515abc768f9aa995d15e8678638e34a4b1ce925797a216bc7b5b26ab8ea97be7
7
+ data.tar.gz: 01edbccd59380207d979f9a504619a862c475217eecd9c8972af5868e4f870e405a511babb6925a7723038c7da395a94ecbaf1a3e3e8fb1f4f07dd7300d0321a
data/CHANGELOG.md CHANGED
@@ -1,260 +1,371 @@
1
- ## Rails 8.0.2.1 (August 13, 2025) ##
1
+ ## Rails 8.1.0.beta1 (September 04, 2025) ##
2
2
 
3
- * No changes.
3
+ * Add `ActiveSupport::Cache::Store#namespace=` and `#namespace`.
4
4
 
5
+ Can be used as an alternative to `Store#clear` in some situations such as parallel
6
+ testing.
5
7
 
6
- ## Rails 8.0.2 (March 12, 2025) ##
7
-
8
- * No changes.
9
-
10
-
11
- ## Rails 8.0.2 (March 12, 2025) ##
8
+ *Nick Schwaderer*
12
9
 
13
- * Fix setting `to_time_preserves_timezone` from `new_framework_defaults_8_0.rb`.
10
+ * Create `parallel_worker_id` helper for running parallel tests. This allows users to
11
+ know which worker they are currently running in.
14
12
 
15
- *fatkodima*
13
+ *Nick Schwaderer*
16
14
 
17
- * Fix Active Support Cache `fetch_multi` when local store is active.
15
+ * Make the cache of `ActiveSupport::Cache::Strategy::LocalCache::Middleware` updatable.
18
16
 
19
- `fetch_multi` now properly yield to the provided block for missing entries
20
- that have been recorded as such in the local store.
17
+ If the cache client at `Rails.cache` of a booted application changes, the corresponding
18
+ mounted middleware needs to update in order for request-local caches to be setup properly.
19
+ Otherwise, redundant cache operations will erroneously hit the datastore.
21
20
 
22
- *Jean Boussier*
21
+ *Gannon McGibbon*
23
22
 
24
- * Fix execution wrapping to report all exceptions, including `Exception`.
23
+ * Add `assert_events_reported` test helper for `ActiveSupport::EventReporter`.
25
24
 
26
- If a more serious error like `SystemStackError` or `NoMemoryError` happens,
27
- the error reporter should be able to report these kinds of exceptions.
25
+ This new assertion allows testing multiple events in a single block, regardless of order:
28
26
 
29
- *Gannon McGibbon*
27
+ ```ruby
28
+ assert_events_reported([
29
+ { name: "user.created", payload: { id: 123 } },
30
+ { name: "email.sent", payload: { to: "user@example.com" } }
31
+ ]) do
32
+ create_user_and_send_welcome_email
33
+ end
34
+ ```
30
35
 
31
- * Fix `RedisCacheStore` and `MemCacheStore` to also handle connection pool related errors.
36
+ *George Ma*
32
37
 
33
- These errors are rescued and reported to `Rails.error`.
38
+ * Add `ActiveSupport::TimeZone#standard_name` method.
34
39
 
35
- *Jean Boussier*
40
+ ``` ruby
41
+ zone = ActiveSupport::TimeZone['Hawaii']
42
+ # Old way
43
+ ActiveSupport::TimeZone::MAPPING[zone.name]
44
+ # New way
45
+ zone.standard_name # => 'Pacific/Honolulu'
46
+ ```
36
47
 
37
- * Fix `ActiveSupport::Cache#read_multi` to respect version expiry when using local cache.
48
+ *Bogdan Gusiev*
38
49
 
39
- *zzak*
50
+ * Add Structured Event Reporter, accessible via `Rails.event`.
40
51
 
41
- * Fix `ActiveSupport::MessageVerifier` and `ActiveSupport::MessageEncryptor` configuration of `on_rotation` callback.
52
+ The Event Reporter provides a unified interface for producing structured events in Rails
53
+ applications:
42
54
 
43
55
  ```ruby
44
- verifier.rotate(old_secret).on_rotation { ... }
56
+ Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
45
57
  ```
46
58
 
47
- Now both work as documented.
59
+ It supports adding tags to events:
48
60
 
49
- *Jean Boussier*
50
-
51
- * Fix `ActiveSupport::MessageVerifier` to always be able to verify both URL-safe and URL-unsafe payloads.
52
-
53
- This is to allow transitioning seemlessly from either configuration without immediately invalidating
54
- all previously generated signed messages.
61
+ ```ruby
62
+ Rails.event.tagged("graphql") do
63
+ # Event includes tags: { graphql: true }
64
+ Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
65
+ end
66
+ ```
55
67
 
56
- *Jean Boussier*, *Florent Beaurain*, *Ali Sepehri*
68
+ As well as context:
69
+ ```ruby
70
+ # All events will contain context: {request_id: "abc123", shop_id: 456}
71
+ Rails.event.set_context(request_id: "abc123", shop_id: 456)
72
+ ```
57
73
 
58
- * Fix `cache.fetch` to honor the provided expiry when `:race_condition_ttl` is used.
74
+ Events are emitted to subscribers. Applications register subscribers to
75
+ control how events are serialized and emitted. Subscribers must implement
76
+ an `#emit` method, which receives the event hash:
59
77
 
60
78
  ```ruby
61
- cache.fetch("key", expires_in: 1.hour, race_condition_ttl: 5.second) do
62
- "something"
79
+ class LogSubscriber
80
+ def emit(event)
81
+ payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ")
82
+ source_location = event[:source_location]
83
+ log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}"
84
+ Rails.logger.info(log)
85
+ end
63
86
  end
64
87
  ```
65
88
 
66
- In the above example, the final cache entry would have a 10 seconds TTL instead
67
- of the requested 1 hour.
89
+ *Adrianna Chang*
68
90
 
69
- *Dhia*
91
+ * Make `ActiveSupport::Logger` `#freeze`-friendly.
70
92
 
71
- * Better handle procs with splat arguments in `set_callback`.
93
+ *Joshua Young*
72
94
 
73
- *Radamés Roriz*
95
+ * Make `ActiveSupport::Gzip.compress` deterministic based on input.
74
96
 
75
- * Fix `String#mb_chars` to not mutate the receiver.
97
+ `ActiveSupport::Gzip.compress` used to include a timestamp in the output,
98
+ causing consecutive calls with the same input data to have different output
99
+ if called during different seconds. It now always sets the timestamp to `0`
100
+ so that the output is identical for any given input.
76
101
 
77
- Previously it would call `force_encoding` on the receiver,
78
- now it dups the receiver first.
102
+ *Rob Brackett*
79
103
 
80
- *Jean Boussier*
104
+ * Given an array of `Thread::Backtrace::Location` objects, the new method
105
+ `ActiveSupport::BacktraceCleaner#clean_locations` returns an array with the
106
+ clean ones:
81
107
 
82
- * Improve `ErrorSubscriber` to also mark error causes as reported.
108
+ ```ruby
109
+ clean_locations = backtrace_cleaner.clean_locations(caller_locations)
110
+ ```
83
111
 
84
- This avoid some cases of errors being reported twice, notably in views because of how
85
- errors are wrapped in `ActionView::Template::Error`.
112
+ Filters and silencers receive strings as usual. However, the `path`
113
+ attributes of the locations in the returned array are the original,
114
+ unfiltered ones, since locations are immutable.
86
115
 
87
- *Jean Boussier*
116
+ *Xavier Noria*
88
117
 
89
- * Fix `Module#module_parent_name` to return the correct name after the module has been named.
118
+ * Improve `CurrentAttributes` and `ExecutionContext` state managment in test cases.
90
119
 
91
- When called on an anonymous module, the return value wouldn't change after the module was given a name
92
- later by being assigned to a constant.
120
+ Previously these two global state would be entirely cleared out whenever calling
121
+ into code that is wrapped by the Rails executor, typically Action Controller or
122
+ Active Job helpers:
93
123
 
94
124
  ```ruby
95
- mod = Module.new
96
- mod.module_parent_name # => "Object"
97
- MyModule::Something = mod
98
- mod.module_parent_name # => "MyModule"
125
+ test "#index works" do
126
+ CurrentUser.id = 42
127
+ get :index
128
+ CurrentUser.id == nil
129
+ end
99
130
  ```
100
131
 
132
+ Now re-entering the executor properly save and restore that state.
133
+
101
134
  *Jean Boussier*
102
135
 
136
+ * The new method `ActiveSupport::BacktraceCleaner#first_clean_location`
137
+ returns the first clean location of the caller's call stack, or `nil`.
138
+ Locations are `Thread::Backtrace::Location` objects. Useful when you want to
139
+ report the application-level location where something happened as an object.
103
140
 
104
- ## Rails 8.0.1 (December 13, 2024) ##
141
+ *Xavier Noria*
105
142
 
106
- * Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceeded by multibyte characters.
143
+ * FileUpdateChecker and EventedFileUpdateChecker ignore changes in Gem.path now.
107
144
 
108
- *Martin Emde*
145
+ *Ermolaev Andrey*, *zzak*
109
146
 
110
- * Restore the ability to decorate methods generated by `class_attribute`.
147
+ * The new method `ActiveSupport::BacktraceCleaner#first_clean_frame` returns
148
+ the first clean frame of the caller's backtrace, or `nil`. Useful when you
149
+ want to report the application-level frame where something happened as a
150
+ string.
111
151
 
112
- It always has been complicated to use Module#prepend or an alias method chain
113
- to decorate methods defined by `class_attribute`, but became even harder in 8.0.
152
+ *Xavier Noria*
114
153
 
115
- This capability is now supported for both reader and writer methods.
154
+ * Always clear `CurrentAttributes` instances.
116
155
 
117
- *Jean Boussier*
156
+ Previously `CurrentAttributes` instance would be reset at the end of requests.
157
+ Meaning its attributes would be re-initialized.
118
158
 
159
+ This is problematic because it assume these objects don't hold any state
160
+ other than their declared attribute, which isn't always the case, and
161
+ can lead to state leak across request.
119
162
 
120
- ## Rails 8.0.0.1 (December 10, 2024) ##
163
+ Now `CurrentAttributes` instances are abandoned at the end of a request,
164
+ and a new instance is created at the start of the next request.
121
165
 
122
- * No changes.
166
+ *Jean Boussier*, *Janko Marohnić*
123
167
 
168
+ * Add public API for `before_fork_hook` in parallel testing.
124
169
 
125
- ## Rails 8.0.0 (November 07, 2024) ##
170
+ Introduces a public API for calling the before fork hooks implemented by parallel testing.
126
171
 
127
- * No changes.
172
+ ```ruby
173
+ parallelize_before_fork do
174
+ # perform an action before test processes are forked
175
+ end
176
+ ```
128
177
 
178
+ *Eileen M. Uchitelle*
129
179
 
130
- ## Rails 8.0.0.rc2 (October 30, 2024) ##
180
+ * Implement ability to skip creating parallel testing databases.
131
181
 
132
- * No changes.
182
+ With parallel testing, Rails will create a database per process. If this isn't
183
+ desirable or you would like to implement databases handling on your own, you can
184
+ now turn off this default behavior.
133
185
 
186
+ To skip creating a database per process, you can change it via the
187
+ `parallelize` method:
134
188
 
135
- ## Rails 8.0.0.rc1 (October 19, 2024) ##
189
+ ```ruby
190
+ parallelize(workers: 10, parallelize_databases: false)
191
+ ```
136
192
 
137
- * Remove deprecated support to passing an array of strings to `ActiveSupport::Deprecation#warn`.
193
+ or via the application configuration:
138
194
 
139
- *Rafael Mendonça França*
195
+ ```ruby
196
+ config.active_support.parallelize_databases = false
197
+ ```
140
198
 
141
- * Remove deprecated support to setting `attr_internal_naming_format` with a `@` prefix.
199
+ *Eileen M. Uchitelle*
142
200
 
143
- *Rafael Mendonça França*
201
+ * Allow to configure maximum cache key sizes
144
202
 
145
- * Remove deprecated `ActiveSupport::ProxyObject`.
203
+ When the key exceeds the configured limit (250 bytes by default), it will be truncated and
204
+ the digest of the rest of the key appended to it.
146
205
 
147
- *Rafael Mendonça França*
206
+ Note that previously `ActiveSupport::Cache::RedisCacheStore` allowed up to 1kb cache keys before
207
+ truncation, which is now reduced to 250 bytes.
148
208
 
149
- * Don't execute i18n watcher on boot. It shouldn't catch any file changes initially,
150
- and unnecessarily slows down boot of applications with lots of translations.
209
+ ```ruby
210
+ config.cache_store = :redis_cache_store, { max_key_size: 64 }
211
+ ```
151
212
 
152
- *Gannon McGibbon*, *David Stosik*
213
+ *fatkodima*
153
214
 
154
- * Fix `ActiveSupport::HashWithIndifferentAccess#stringify_keys` to stringify all keys not just symbols.
215
+ * Use `UNLINK` command instead of `DEL` in `ActiveSupport::Cache::RedisCacheStore` for non-blocking deletion.
155
216
 
156
- Previously:
217
+ *Aron Roh*
218
+
219
+ * Add `Cache#read_counter` and `Cache#write_counter`
157
220
 
158
221
  ```ruby
159
- { 1 => 2 }.with_indifferent_access.stringify_keys[1] # => 2
222
+ Rails.cache.write_counter("foo", 1)
223
+ Rails.cache.read_counter("foo") # => 1
224
+ Rails.cache.increment("foo")
225
+ Rails.cache.read_counter("foo") # => 2
160
226
  ```
161
227
 
162
- After this change:
228
+ *Alex Ghiculescu*
229
+
230
+ * Introduce ActiveSupport::Testing::ErrorReporterAssertions#capture_error_reports
231
+
232
+ Captures all reported errors from within the block that match the given
233
+ error class.
163
234
 
164
235
  ```ruby
165
- { 1 => 2 }.with_indifferent_access.stringify_keys["1"] # => 2
236
+ reports = capture_error_reports(IOError) do
237
+ Rails.error.report(IOError.new("Oops"))
238
+ Rails.error.report(IOError.new("Oh no"))
239
+ Rails.error.report(StandardError.new)
240
+ end
241
+
242
+ assert_equal 2, reports.size
243
+ assert_equal "Oops", reports.first.error.message
244
+ assert_equal "Oh no", reports.last.error.message
166
245
  ```
167
246
 
168
- This change can be seen as a bug fix, but since it behaved like this for a very long time, we're deciding
169
- to not backport the fix and to make the change in a major release.
247
+ *Andrew Novoselac*
170
248
 
171
- *Jean Boussier*
249
+ * Introduce ActiveSupport::ErrorReporter#add_middleware
172
250
 
173
- ## Rails 8.0.0.beta1 (September 26, 2024) ##
251
+ When reporting an error, the error context middleware will be called with the reported error
252
+ and base execution context. The stack may mutate the context hash. The mutated context will
253
+ then be passed to error subscribers. Middleware receives the same parameters as `ErrorReporter#report`.
174
254
 
175
- * Include options when instrumenting `ActiveSupport::Cache::Store#delete` and `ActiveSupport::Cache::Store#delete_multi`.
255
+ *Andrew Novoselac*, *Sam Schmidt*
176
256
 
177
- *Adam Renberg Tamm*
257
+ * Change execution wrapping to report all exceptions, including `Exception`.
178
258
 
179
- * Print test names when running `rails test -v` for parallel tests.
259
+ If a more serious error like `SystemStackError` or `NoMemoryError` happens,
260
+ the error reporter should be able to report these kinds of exceptions.
180
261
 
181
- *John Hawthorn*, *Abeid Ahmed*
262
+ *Gannon McGibbon*
182
263
 
183
- * Deprecate `Benchmark.ms` core extension.
264
+ * `ActiveSupport::Testing::Parallelization.before_fork_hook` allows declaration of callbacks that
265
+ are invoked immediately before forking test workers.
184
266
 
185
- The `benchmark` gem will become bundled in Ruby 3.5
267
+ *Mike Dalessio*
186
268
 
187
- *Earlopain*
269
+ * Allow the `#freeze_time` testing helper to accept a date or time argument.
188
270
 
189
- * `ActiveSupport::TimeWithZone#inspect` now uses ISO 8601 style time like `Time#inspect`
271
+ ```ruby
272
+ Time.current # => Sun, 09 Jul 2024 15:34:49 EST -05:00
273
+ freeze_time Time.current + 1.day
274
+ sleep 1
275
+ Time.current # => Mon, 10 Jul 2024 15:34:49 EST -05:00
276
+ ```
190
277
 
191
- *John Hawthorn*
278
+ *Joshua Young*
192
279
 
193
- * `ActiveSupport::ErrorReporter#report` now assigns a backtrace to unraised exceptions.
280
+ * `ActiveSupport::JSON` now accepts options
194
281
 
195
- Previously reporting an un-raised exception would result in an error report without
196
- a backtrace. Now it automatically generates one.
282
+ It is now possible to pass options to `ActiveSupport::JSON`:
283
+ ```ruby
284
+ ActiveSupport::JSON.decode('{"key": "value"}', symbolize_names: true) # => { key: "value" }
285
+ ```
197
286
 
198
- *Jean Boussier*
287
+ *matthaigh27*
199
288
 
200
- * Add `escape_html_entities` option to `ActiveSupport::JSON.encode`.
289
+ * `ActiveSupport::Testing::NotificationAssertions`'s `assert_notification` now matches against payload subsets by default.
201
290
 
202
- This allows for overriding the global configuration found at
203
- `ActiveSupport.escape_html_entities_in_json` for specific calls to `to_json`.
291
+ Previously the following assertion would fail due to excess key vals in the notification payload. Now with payload subset matching, it will pass.
204
292
 
205
- This should be usable from controllers in the following manner:
206
293
  ```ruby
207
- class MyController < ApplicationController
208
- def index
209
- render json: { hello: "world" }, escape_html_entities: false
210
- end
294
+ assert_notification("post.submitted", title: "Cool Post") do
295
+ ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: "Cool Body")
211
296
  end
212
297
  ```
213
298
 
214
- *Nigel Baillie*
299
+ Additionally, you can now persist a matched notification for more customized assertions.
215
300
 
216
- * Raise when using key which can't respond to `#to_sym` in `EncryptedConfiguration`.
301
+ ```ruby
302
+ notification = assert_notification("post.submitted", title: "Cool Post") do
303
+ ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: Body.new("Cool Body"))
304
+ end
217
305
 
218
- As is the case when trying to use an Integer or Float as a key, which is unsupported.
306
+ assert_instance_of(Body, notification.payload[:body])
307
+ ```
219
308
 
220
- *zzak*
309
+ *Nicholas La Roux*
221
310
 
222
- * Deprecate addition and since between two `Time` and `ActiveSupport::TimeWithZone`.
311
+ * Deprecate `String#mb_chars` and `ActiveSupport::Multibyte::Chars`.
223
312
 
224
- Previously adding time instances together such as `10.days.ago + 10.days.ago` or `10.days.ago.since(10.days.ago)` produced a nonsensical future date. This behavior is deprecated and will be removed in Rails 8.1.
313
+ These APIs are a relic of the Ruby 1.8 days when Ruby strings weren't encoding
314
+ aware. There is no legitimate reasons to need these APIs today.
225
315
 
226
- *Nick Schwaderer*
316
+ *Jean Boussier*
227
317
 
228
- * Support rfc2822 format for Time#to_fs & Date#to_fs.
318
+ * Deprecate `ActiveSupport::Configurable`
229
319
 
230
- *Akshay Birajdar*
320
+ *Sean Doyle*
231
321
 
232
- * Optimize load time for `Railtie#initialize_i18n`. Filter `I18n.load_path`s passed to the file watcher to only those
233
- under `Rails.root`. Previously the watcher would grab all available locales, including those in gems
234
- which do not require a watcher because they won't change.
322
+ * `nil.to_query("key")` now returns `key`.
235
323
 
236
- *Nick Schwaderer*
324
+ Previously it would return `key=`, preventing round tripping with `Rack::Utils.parse_nested_query`.
325
+
326
+ *Erol Fornoles*
237
327
 
238
- * Add a `filter` option to `in_order_of` to prioritize certain values in the sorting without filtering the results
239
- by these values.
328
+ * Avoid wrapping redis in a `ConnectionPool` when using `ActiveSupport::Cache::RedisCacheStore` if the `:redis`
329
+ option is already a `ConnectionPool`.
240
330
 
241
- *Igor Depolli*
331
+ *Joshua Young*
242
332
 
243
- * Improve error message when using `assert_difference` or `assert_changes` with a
244
- proc by printing the proc's source code (MRI only).
333
+ * Alter `ERB::Util.tokenize` to return :PLAIN token with full input string when string doesn't contain ERB tags.
245
334
 
246
- *Richard Böhme*, *Jean Boussier*
335
+ *Martin Emde*
336
+
337
+ * Fix a bug in `ERB::Util.tokenize` that causes incorrect tokenization when ERB tags are preceded by multibyte characters.
247
338
 
248
- * Add a new configuration value `:zone` for `ActiveSupport.to_time_preserves_timezone` and rename the previous `true` value to `:offset`. The new default value is `:zone`.
339
+ *Martin Emde*
249
340
 
250
- *Jason Kim*, *John Hawthorn*
341
+ * Add `ActiveSupport::Testing::NotificationAssertions` module to help with testing `ActiveSupport::Notifications`.
342
+
343
+ *Nicholas La Roux*, *Yishu See*, *Sean Doyle*
344
+
345
+ * `ActiveSupport::CurrentAttributes#attributes` now will return a new hash object on each call.
346
+
347
+ Previously, the same hash object was returned each time that method was called.
348
+
349
+ *fatkodima*
251
350
 
252
- * Align instrumentation `payload[:key]` in ActiveSupport::Cache to follow the same pattern, with namespaced and normalized keys.
351
+ * `ActiveSupport::JSON.encode` supports CIDR notation.
352
+
353
+ Previously:
354
+
355
+ ```ruby
356
+ ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0\""
357
+ ```
358
+
359
+ After this change:
360
+
361
+ ```ruby
362
+ ActiveSupport::JSON.encode(IPAddr.new("172.16.0.0/24")) # => "\"172.16.0.0/24\""
363
+ ```
253
364
 
254
- *Frederik Erbs Spang Thomsen*
365
+ *Taketo Takashima*
255
366
 
256
- * Fix `travel_to` to set usec 0 when `with_usec` is `false` and the given argument String or DateTime.
367
+ * Make `ActiveSupport::FileUpdateChecker` faster when checking many file-extensions.
257
368
 
258
- *mopp*
369
+ *Jonathan del Strother*
259
370
 
260
- Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activesupport/CHANGELOG.md) for previous changes.
371
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activesupport/CHANGELOG.md) for previous changes.
data/README.rdoc CHANGED
@@ -35,6 +35,6 @@ Bug reports for the Ruby on \Rails project can be filed here:
35
35
 
36
36
  * https://github.com/rails/rails/issues
37
37
 
38
- Feature requests should be discussed on the rails-core mailing list here:
38
+ Feature requests should be discussed on the rubyonrails-core forum here:
39
39
 
40
40
  * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -56,6 +56,18 @@ module ActiveSupport
56
56
  end
57
57
  alias :filter :clean
58
58
 
59
+ # Given an array of Thread::Backtrace::Location objects, returns an array
60
+ # with the clean ones:
61
+ #
62
+ # clean_locations = backtrace_cleaner.clean_locations(caller_locations)
63
+ #
64
+ # Filters and silencers receive strings as usual. However, the +path+
65
+ # attributes of the locations in the returned array are the original,
66
+ # unfiltered ones, since locations are immutable.
67
+ def clean_locations(locations, kind = :silent)
68
+ locations.select { |location| clean_frame(location, kind) }
69
+ end
70
+
59
71
  # Returns the frame with all filters applied.
60
72
  # returns +nil+ if the frame was silenced.
61
73
  def clean_frame(frame, kind = :silent)
@@ -74,6 +86,65 @@ module ActiveSupport
74
86
  end
75
87
  end
76
88
 
89
+ # Thread.each_caller_location does not accept a start in Ruby < 3.4.
90
+ if Thread.method(:each_caller_location).arity == 0
91
+ # Returns the first clean frame of the caller's backtrace, or +nil+.
92
+ #
93
+ # Frames are strings.
94
+ def first_clean_frame(kind = :silent)
95
+ caller_location_skipped = false
96
+
97
+ Thread.each_caller_location do |location|
98
+ unless caller_location_skipped
99
+ caller_location_skipped = true
100
+ next
101
+ end
102
+
103
+ frame = clean_frame(location, kind)
104
+ return frame if frame
105
+ end
106
+ end
107
+
108
+ # Returns the first clean location of the caller's call stack, or +nil+.
109
+ #
110
+ # Locations are Thread::Backtrace::Location objects. Since they are
111
+ # immutable, their +path+ attributes are the original ones, but filters
112
+ # are applied internally so silencers can still rely on them.
113
+ def first_clean_location(kind = :silent)
114
+ caller_location_skipped = false
115
+
116
+ Thread.each_caller_location do |location|
117
+ unless caller_location_skipped
118
+ caller_location_skipped = true
119
+ next
120
+ end
121
+
122
+ return location if clean_frame(location, kind)
123
+ end
124
+ end
125
+ else
126
+ # Returns the first clean frame of the caller's backtrace, or +nil+.
127
+ #
128
+ # Frames are strings.
129
+ def first_clean_frame(kind = :silent)
130
+ Thread.each_caller_location(2) do |location|
131
+ frame = clean_frame(location, kind)
132
+ return frame if frame
133
+ end
134
+ end
135
+
136
+ # Returns the first clean location of the caller's call stack, or +nil+.
137
+ #
138
+ # Locations are Thread::Backtrace::Location objects. Since they are
139
+ # immutable, their +path+ attributes are the original ones, but filters
140
+ # are applied internally so silencers can still rely on them.
141
+ def first_clean_location(kind = :silent)
142
+ Thread.each_caller_location(2) do |location|
143
+ return location if clean_frame(location, kind)
144
+ end
145
+ end
146
+ end
147
+
77
148
  # Adds a filter from the block provided. Each line in the backtrace will be
78
149
  # mapped against this filter.
79
150
  #