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