activesupport 7.0.10 → 7.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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +703 -361
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_support/actionable_error.rb +3 -1
  6. data/lib/active_support/array_inquirer.rb +2 -0
  7. data/lib/active_support/backtrace_cleaner.rb +25 -5
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/builder.rb +1 -1
  10. data/lib/active_support/cache/coder.rb +153 -0
  11. data/lib/active_support/cache/entry.rb +128 -0
  12. data/lib/active_support/cache/file_store.rb +37 -10
  13. data/lib/active_support/cache/mem_cache_store.rb +84 -68
  14. data/lib/active_support/cache/memory_store.rb +76 -26
  15. data/lib/active_support/cache/null_store.rb +6 -0
  16. data/lib/active_support/cache/redis_cache_store.rb +126 -131
  17. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  18. data/lib/active_support/cache/strategy/local_cache.rb +20 -8
  19. data/lib/active_support/cache.rb +304 -246
  20. data/lib/active_support/callbacks.rb +38 -18
  21. data/lib/active_support/concern.rb +4 -2
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
  23. data/lib/active_support/concurrency/null_lock.rb +13 -0
  24. data/lib/active_support/configurable.rb +10 -0
  25. data/lib/active_support/core_ext/array/conversions.rb +2 -1
  26. data/lib/active_support/core_ext/array.rb +0 -1
  27. data/lib/active_support/core_ext/class/attribute.rb +1 -0
  28. data/lib/active_support/core_ext/class/subclasses.rb +13 -10
  29. data/lib/active_support/core_ext/date/conversions.rb +1 -0
  30. data/lib/active_support/core_ext/date.rb +0 -1
  31. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  32. data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
  33. data/lib/active_support/core_ext/date_time.rb +0 -1
  34. data/lib/active_support/core_ext/digest/uuid.rb +1 -10
  35. data/lib/active_support/core_ext/enumerable.rb +3 -75
  36. data/lib/active_support/core_ext/erb/util.rb +196 -0
  37. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  38. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  39. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  40. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  41. data/lib/active_support/core_ext/module/delegation.rb +40 -11
  42. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  43. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  44. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  45. data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
  46. data/lib/active_support/core_ext/numeric.rb +0 -1
  47. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  48. data/lib/active_support/core_ext/object/duplicable.rb +15 -24
  49. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  50. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  51. data/lib/active_support/core_ext/object/json.rb +14 -8
  52. data/lib/active_support/core_ext/object/with.rb +44 -0
  53. data/lib/active_support/core_ext/object/with_options.rb +4 -4
  54. data/lib/active_support/core_ext/object.rb +1 -0
  55. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  56. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  57. data/lib/active_support/core_ext/pathname.rb +1 -0
  58. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  59. data/lib/active_support/core_ext/range/overlap.rb +12 -0
  60. data/lib/active_support/core_ext/range.rb +1 -2
  61. data/lib/active_support/core_ext/securerandom.rb +24 -12
  62. data/lib/active_support/core_ext/string/filters.rb +20 -14
  63. data/lib/active_support/core_ext/string/indent.rb +1 -1
  64. data/lib/active_support/core_ext/string/inflections.rb +16 -5
  65. data/lib/active_support/core_ext/string/output_safety.rb +38 -174
  66. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  67. data/lib/active_support/core_ext/time/calculations.rb +18 -2
  68. data/lib/active_support/core_ext/time/conversions.rb +2 -2
  69. data/lib/active_support/core_ext/time/zones.rb +4 -4
  70. data/lib/active_support/core_ext/time.rb +0 -1
  71. data/lib/active_support/current_attributes.rb +15 -6
  72. data/lib/active_support/dependencies/autoload.rb +17 -12
  73. data/lib/active_support/deprecation/behaviors.rb +55 -34
  74. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  75. data/lib/active_support/deprecation/deprecators.rb +104 -0
  76. data/lib/active_support/deprecation/disallowed.rb +3 -5
  77. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  78. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  79. data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
  80. data/lib/active_support/deprecation/reporting.rb +40 -29
  81. data/lib/active_support/deprecation.rb +32 -5
  82. data/lib/active_support/deprecator.rb +7 -0
  83. data/lib/active_support/descendants_tracker.rb +104 -132
  84. data/lib/active_support/duration/iso8601_serializer.rb +0 -2
  85. data/lib/active_support/duration.rb +2 -1
  86. data/lib/active_support/encrypted_configuration.rb +30 -9
  87. data/lib/active_support/encrypted_file.rb +8 -3
  88. data/lib/active_support/environment_inquirer.rb +22 -2
  89. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  90. data/lib/active_support/error_reporter.rb +121 -35
  91. data/lib/active_support/execution_wrapper.rb +4 -4
  92. data/lib/active_support/file_update_checker.rb +4 -2
  93. data/lib/active_support/fork_tracker.rb +10 -2
  94. data/lib/active_support/gem_version.rb +4 -4
  95. data/lib/active_support/gzip.rb +2 -0
  96. data/lib/active_support/hash_with_indifferent_access.rb +35 -17
  97. data/lib/active_support/i18n.rb +1 -1
  98. data/lib/active_support/i18n_railtie.rb +20 -13
  99. data/lib/active_support/inflector/inflections.rb +2 -0
  100. data/lib/active_support/inflector/methods.rb +23 -11
  101. data/lib/active_support/inflector/transliterate.rb +3 -1
  102. data/lib/active_support/isolated_execution_state.rb +26 -22
  103. data/lib/active_support/json/decoding.rb +2 -1
  104. data/lib/active_support/json/encoding.rb +25 -43
  105. data/lib/active_support/key_generator.rb +9 -1
  106. data/lib/active_support/lazy_load_hooks.rb +6 -4
  107. data/lib/active_support/locale/en.yml +2 -0
  108. data/lib/active_support/log_subscriber.rb +78 -33
  109. data/lib/active_support/logger.rb +1 -1
  110. data/lib/active_support/logger_thread_safe_level.rb +9 -22
  111. data/lib/active_support/message_encryptor.rb +197 -53
  112. data/lib/active_support/message_encryptors.rb +140 -0
  113. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  114. data/lib/active_support/message_pack/extensions.rb +292 -0
  115. data/lib/active_support/message_pack/serializer.rb +63 -0
  116. data/lib/active_support/message_pack.rb +50 -0
  117. data/lib/active_support/message_verifier.rb +212 -93
  118. data/lib/active_support/message_verifiers.rb +134 -0
  119. data/lib/active_support/messages/codec.rb +65 -0
  120. data/lib/active_support/messages/metadata.rb +111 -45
  121. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  122. data/lib/active_support/messages/rotator.rb +34 -32
  123. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  124. data/lib/active_support/multibyte/chars.rb +2 -0
  125. data/lib/active_support/multibyte/unicode.rb +9 -37
  126. data/lib/active_support/notifications/fanout.rb +239 -81
  127. data/lib/active_support/notifications/instrumenter.rb +79 -30
  128. data/lib/active_support/notifications.rb +1 -1
  129. data/lib/active_support/number_helper/number_converter.rb +5 -14
  130. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  131. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  132. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  133. data/lib/active_support/number_helper.rb +318 -379
  134. data/lib/active_support/ordered_hash.rb +3 -3
  135. data/lib/active_support/ordered_options.rb +14 -0
  136. data/lib/active_support/parameter_filter.rb +84 -69
  137. data/lib/active_support/proxy_object.rb +2 -0
  138. data/lib/active_support/railtie.rb +33 -21
  139. data/lib/active_support/reloader.rb +12 -4
  140. data/lib/active_support/rescuable.rb +2 -0
  141. data/lib/active_support/secure_compare_rotator.rb +16 -9
  142. data/lib/active_support/string_inquirer.rb +3 -1
  143. data/lib/active_support/subscriber.rb +9 -27
  144. data/lib/active_support/syntax_error_proxy.rb +49 -0
  145. data/lib/active_support/tagged_logging.rb +60 -24
  146. data/lib/active_support/test_case.rb +153 -6
  147. data/lib/active_support/testing/assertions.rb +26 -10
  148. data/lib/active_support/testing/autorun.rb +0 -2
  149. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  150. data/lib/active_support/testing/deprecation.rb +25 -25
  151. data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
  152. data/lib/active_support/testing/isolation.rb +1 -1
  153. data/lib/active_support/testing/method_call_assertions.rb +21 -8
  154. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  155. data/lib/active_support/testing/stream.rb +1 -1
  156. data/lib/active_support/testing/strict_warnings.rb +38 -0
  157. data/lib/active_support/testing/time_helpers.rb +32 -14
  158. data/lib/active_support/time_with_zone.rb +4 -14
  159. data/lib/active_support/values/time_zone.rb +9 -7
  160. data/lib/active_support/version.rb +1 -1
  161. data/lib/active_support/xml_mini/jdom.rb +3 -10
  162. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  163. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  164. data/lib/active_support/xml_mini/rexml.rb +1 -1
  165. data/lib/active_support/xml_mini.rb +2 -2
  166. data/lib/active_support.rb +13 -3
  167. metadata +48 -58
  168. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  169. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
  170. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
  171. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  172. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
  173. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
  174. data/lib/active_support/core_ext/range/overlaps.rb +0 -36
  175. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
  176. data/lib/active_support/core_ext/uri.rb +0 -5
  177. data/lib/active_support/per_thread_registry.rb +0 -65
data/CHANGELOG.md CHANGED
@@ -1,666 +1,1008 @@
1
- ## Rails 7.0.10 (October 28, 2025) ##
1
+ ## Rails 7.1.0.beta1 (September 13, 2023) ##
2
2
 
3
- * No changes.
4
-
5
-
6
- ## Rails 7.0.9 (October 28, 2025) ##
3
+ * Add `drb`, `mutex_m` and `base64` that are bundled gem candidates for Ruby 3.4
7
4
 
8
- * Fix `ActiveSupport::Notifications.publish_event` to preserve units.
5
+ *Yasuo Honda*
9
6
 
10
- This solves the incorrect reporting of time spent running Active Record
11
- asynchronous queries (by a factor `1000`).
7
+ * When using cache format version >= 7.1 or a custom serializer, expired and
8
+ version-mismatched cache entries can now be detected without deserializing
9
+ their values.
12
10
 
13
- *Jean Boussier*
11
+ *Jonathan Hefner*
14
12
 
15
- * Fix ActiveSupport::Deprecation to handle blaming generated code
13
+ * Make all cache stores return a boolean for `#delete`
16
14
 
17
- *Jean Boussier*, *fatkodima*
15
+ Previously the `RedisCacheStore#delete` would return `1` if the entry
16
+ exists and `0` otherwise. Now it returns true if the entry exists and false
17
+ otherwise, just like the other stores.
18
18
 
19
- * Fix `#to_fs(:human_size)` to correctly work with negative numbers.
19
+ The `FileStore` would return `nil` if the entry doesn't exists and returns
20
+ `false` now as well.
20
21
 
21
- *Earlopain*
22
+ *Petrik de Heus*
22
23
 
23
- * Add `bigdecimal` as Active Support dependency that is a bundled gem candidate for Ruby 3.4.
24
+ * Active Support cache stores now support replacing the default compressor via
25
+ a `:compressor` option. The specified compressor must respond to `deflate`
26
+ and `inflate`. For example:
24
27
 
25
- `bigdecimal` 3.1.4 or higher version will be installed.
26
- Ruby 2.7 and 3.0 users who want `bigdecimal` version 2.0.0 or 3.0.0 behavior as a default gem,
27
- pin the `bigdecimal` version in your application Gemfile.
28
+ ```ruby
29
+ module MyCompressor
30
+ def self.deflate(string)
31
+ # compression logic...
32
+ end
28
33
 
29
- *Koichi ITO*
34
+ def self.inflate(compressed)
35
+ # decompression logic...
36
+ end
37
+ end
30
38
 
31
- * Ensure `{down,up}case_first` returns non-frozen string.
39
+ config.cache_store = :redis_cache_store, { compressor: MyCompressor }
40
+ ```
32
41
 
33
42
  *Jonathan Hefner*
34
43
 
35
- * Add `drb`, `mutex_m` and `base64` that are bundled gem candidates for Ruby 3.4
44
+ * Active Support cache stores now support a `:serializer` option. Similar to
45
+ the `:coder` option, serializers must respond to `dump` and `load`. However,
46
+ serializers are only responsible for serializing a cached value, whereas
47
+ coders are responsible for serializing the entire `ActiveSupport::Cache::Entry`
48
+ instance. Additionally, the output from serializers can be automatically
49
+ compressed, whereas coders are responsible for their own compression.
36
50
 
37
- *Yasuo Honda*
51
+ Specifying a serializer instead of a coder also enables performance
52
+ optimizations, including the bare string optimization introduced by cache
53
+ format version 7.1.
38
54
 
39
- * Fix `delete_matched` for file cache store to work with keys longer than the
40
- max filename size.
55
+ The `:serializer` and `:coder` options are mutually exclusive. Specifying
56
+ both will raise an `ArgumentError`.
41
57
 
42
- *fatkodima* and *Jonathan Hefner*
58
+ *Jonathan Hefner*
43
59
 
44
- * Fix MemoryStore to prevent race conditions when incrementing or decrementing.
60
+ * Fix `ActiveSupport::Inflector.humanize(nil)` raising ``NoMethodError: undefined method `end_with?' for nil:NilClass``.
45
61
 
46
- *Pierre Jambet*
62
+ *James Robinson*
47
63
 
48
- * Fix MemoryStore to preserve entries TTL when incrementing or decrementing
64
+ * Don't show secrets for `ActiveSupport::KeyGenerator#inspect`.
49
65
 
50
- This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.
66
+ Before:
51
67
 
52
- *Jean Boussier*
68
+ ```ruby
69
+ ActiveSupport::KeyGenerator.new(secret).inspect
70
+ "#<ActiveSupport::KeyGenerator:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
71
+ ```
53
72
 
54
- * NumberHelper: handle objects responding to_d.
73
+ After:
55
74
 
56
- *fatkodima*
75
+ ```ruby
76
+ ActiveSupport::KeyGenerator::Aes256Gcm(secret).inspect
77
+ "#<ActiveSupport::KeyGenerator:0x0000000104888038>"
78
+ ```
57
79
 
58
- * NumberHelper: handle very large numbers.
80
+ *Petrik de Heus*
59
81
 
60
- *Alex Ghiculescu*, *fatkodima*
82
+ * Improve error message when EventedFileUpdateChecker is used without a
83
+ compatible version of the Listen gem
61
84
 
62
- * Fix Range#overlaps? not taking empty ranges into account on Ruby < 3.3
85
+ *Hartley McGuire*
63
86
 
64
- *Nobuyoshi Nakada*, *Shouichi Kamiya*, *Hartley McGuire*
87
+ * Add `:report` behavior for Deprecation
65
88
 
89
+ Setting `config.active_support.deprecation = :report` uses the error
90
+ reporter to report deprecation warnings to `ActiveSupport::ErrorReporter`.
66
91
 
67
- ## Rails 7.0.8.7 (December 10, 2024) ##
92
+ Deprecations are reported as handled errors, with a severity of `:warning`.
68
93
 
69
- * No changes.
94
+ Useful to report deprecations happening in production to your bug tracker.
70
95
 
96
+ *Étienne Barrié*
71
97
 
72
- ## Rails 7.0.8.6 (October 23, 2024) ##
98
+ * Rename `Range#overlaps?` to `#overlap?` and add alias for backwards compatibility
73
99
 
74
- * No changes.
100
+ *Christian Schmidt*
75
101
 
102
+ * Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
103
+ methods
76
104
 
77
- ## Rails 7.0.8.5 (October 15, 2024) ##
105
+ *Hartley McGuire*
78
106
 
79
- * No changes.
107
+ * Don't show secrets for `MessageEncryptor#inspect`.
80
108
 
109
+ Before:
81
110
 
82
- ## Rails 7.0.8.4 (June 04, 2024) ##
111
+ ```ruby
112
+ ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
113
+ "#<ActiveSupport::MessageEncryptor:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
114
+ ```
83
115
 
84
- * No changes.
116
+ After:
85
117
 
118
+ ```ruby
119
+ ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
120
+ "#<ActiveSupport::MessageEncryptor:0x0000000104888038>"
121
+ ```
86
122
 
87
- ## Rails 7.0.8.3 (May 17, 2024) ##
123
+ *Petrik de Heus*
88
124
 
89
- * No changes.
125
+ * Don't show contents for `EncryptedConfiguration#inspect`.
90
126
 
127
+ Before:
128
+ ```ruby
129
+ Rails.application.credentials.inspect
130
+ "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8 ... @config={:secret=>\"something secret\"} ... @key_file_contents=\"915e4ea054e011022398dc242\" ...>"
131
+ ```
91
132
 
92
- ## Rails 7.0.8.2 (May 16, 2024) ##
133
+ After:
134
+ ```ruby
135
+ Rails.application.credentials.inspect
136
+ "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8>"
137
+ ```
93
138
 
94
- * No changes.
139
+ *Petrik de Heus*
95
140
 
141
+ * `ERB::Util.html_escape_once` always returns an `html_safe` string.
96
142
 
97
- ## Rails 7.0.8.1 (February 21, 2024) ##
143
+ This method previously maintained the `html_safe?` property of a string on the return
144
+ value. Because this string has been escaped, however, not marking it as `html_safe` causes
145
+ entities to be double-escaped.
98
146
 
99
- * No changes.
147
+ As an example, take this view snippet:
100
148
 
149
+ ```html
150
+ <p><%= html_escape_once("this & that &amp; the other") %></p>
151
+ ```
101
152
 
102
- ## Rails 7.0.8 (September 09, 2023) ##
153
+ Before this change, that would be double-escaped and render as:
103
154
 
104
- * Fix `TimeWithZone` still using deprecated `#to_s` when `ENV` or `config` to
105
- disable it are set.
155
+ ```html
156
+ <p>this &amp;amp; that &amp;amp; the other</p>
157
+ ```
106
158
 
107
- *Hartley McGuire*
159
+ After this change, it renders correctly as:
108
160
 
109
- * Fix CacheStore#write_multi when using a distributed Redis cache with a connection pool.
161
+ ```html
162
+ <p>this &amp; that &amp; the other</p>
163
+ ```
110
164
 
111
- Fixes [#48938](https://github.com/rails/rails/issues/48938).
165
+ Fixes #48256
112
166
 
113
- *Jonathan del Strother*
167
+ *Mike Dalessio*
114
168
 
169
+ * Deprecate `SafeBuffer#clone_empty`.
115
170
 
116
- ## Rails 7.0.7.2 (August 22, 2023) ##
171
+ This method has not been used internally since Rails 4.2.0.
117
172
 
118
- * No changes.
173
+ *Mike Dalessio*
119
174
 
175
+ * `MessageEncryptor`, `MessageVerifier`, and `config.active_support.message_serializer`
176
+ now accept `:message_pack` and `:message_pack_allow_marshal` as serializers.
177
+ These serializers require the [`msgpack` gem](https://rubygems.org/gems/msgpack)
178
+ (>= 1.7.0).
179
+
180
+ The Message Pack format can provide improved performance and smaller payload
181
+ sizes. It also supports round-tripping some Ruby types that are not supported
182
+ by JSON. For example:
183
+
184
+ ```ruby
185
+ verifier = ActiveSupport::MessageVerifier.new("secret")
186
+ data = [{ a: 1 }, { b: 2 }.with_indifferent_access, 1.to_d, Time.at(0, 123)]
187
+ message = verifier.generate(data)
188
+
189
+ # BEFORE with config.active_support.message_serializer = :json
190
+ verifier.verified(message)
191
+ # => [{"a"=>1}, {"b"=>2}, "1.0", "1969-12-31T18:00:00.000-06:00"]
192
+ verifier.verified(message).map(&:class)
193
+ # => [Hash, Hash, String, String]
194
+
195
+ # AFTER with config.active_support.message_serializer = :message_pack
196
+ verifier.verified(message)
197
+ # => [{:a=>1}, {"b"=>2}, 0.1e1, 1969-12-31 18:00:00.000123 -0600]
198
+ verifier.verified(message).map(&:class)
199
+ # => [Hash, ActiveSupport::HashWithIndifferentAccess, BigDecimal, Time]
200
+ ```
201
+
202
+ The `:message_pack` serializer can fall back to deserializing with
203
+ `ActiveSupport::JSON` when necessary, and the `:message_pack_allow_marshal`
204
+ serializer can fall back to deserializing with `Marshal` as well as
205
+ `ActiveSupport::JSON`. Additionally, the `:marshal`, `:json`, and
206
+ `:json_allow_marshal` serializers can now fall back to deserializing with
207
+ `ActiveSupport::MessagePack` when necessary. These behaviors ensure old
208
+ messages can still be read so that migration is easier.
120
209
 
121
- ## Rails 7.0.7.1 (August 22, 2023) ##
210
+ *Jonathan Hefner*
122
211
 
123
- * Use a temporary file for storing unencrypted files while editing
212
+ * A new `7.1` cache format is available which includes an optimization for
213
+ bare string values such as view fragments.
124
214
 
125
- [CVE-2023-38037]
215
+ The `7.1` cache format is used by default for new apps, and existing apps
216
+ can enable the format by setting `config.load_defaults 7.1` or by setting
217
+ `config.active_support.cache_format_version = 7.1` in `config/application.rb`
218
+ or a `config/environments/*.rb` file.
126
219
 
220
+ Cache entries written using the `6.1` or `7.0` cache formats can be read
221
+ when using the `7.1` format. To perform a rolling deploy of a Rails 7.1
222
+ upgrade, wherein servers that have not yet been upgraded must be able to
223
+ read caches from upgraded servers, leave the cache format unchanged on the
224
+ first deploy, then enable the `7.1` cache format on a subsequent deploy.
127
225
 
128
- ## Rails 7.0.7 (August 09, 2023) ##
226
+ *Jonathan Hefner*
129
227
 
130
- * Fix `Cache::NullStore` with local caching for repeated reads.
228
+ * Active Support cache stores can now use a preconfigured serializer based on
229
+ `ActiveSupport::MessagePack` via the `:serializer` option:
131
230
 
132
- *fatkodima*
231
+ ```ruby
232
+ config.cache_store = :redis_cache_store, { serializer: :message_pack }
233
+ ```
133
234
 
134
- * Fix `to_s` with no arguments not respecting custom `:default` formats
235
+ The `:message_pack` serializer can reduce cache entry sizes and improve
236
+ performance, but requires the [`msgpack` gem](https://rubygems.org/gems/msgpack)
237
+ (>= 1.7.0).
135
238
 
136
- *Hartley McGuire*
239
+ The `:message_pack` serializer can read cache entries written by the default
240
+ serializer, and the default serializer can now read entries written by the
241
+ `:message_pack` serializer. These behaviors make it easy to migrate between
242
+ serializer without invalidating the entire cache.
137
243
 
138
- * Fix `ActiveSupport::Inflector.humanize(nil)` raising ``NoMethodError: undefined method `end_with?' for nil:NilClass``.
244
+ *Jonathan Hefner*
139
245
 
140
- *James Robinson*
246
+ * `Object#deep_dup` no longer duplicate named classes and modules.
141
247
 
142
- * Fix `Enumerable#sum` for `Enumerator#lazy`.
248
+ Before:
143
249
 
144
- *fatkodima*, *Matthew Draper*, *Jonathan Hefner*
250
+ ```ruby
251
+ hash = { class: Object, module: Kernel }
252
+ hash.deep_dup # => {:class=>#<Class:0x00000001063ffc80>, :module=>#<Module:0x00000001063ffa00>}
253
+ ```
145
254
 
146
- * Improve error message when EventedFileUpdateChecker is used without a
147
- compatible version of the Listen gem
255
+ After:
148
256
 
149
- *Hartley McGuire*
257
+ ```ruby
258
+ hash = { class: Object, module: Kernel }
259
+ hash.deep_dup # => {:class=>Object, :module=>Kernel}
260
+ ```
150
261
 
262
+ *Jean Boussier*
151
263
 
152
- ## Rails 7.0.6 (June 29, 2023) ##
264
+ * Consistently raise an `ArgumentError` if the `ActiveSupport::Cache` key is blank.
153
265
 
154
- * Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
155
- methods
266
+ *Joshua Young*
156
267
 
157
- *Hartley McGuire*
268
+ * Deprecate usage of the singleton `ActiveSupport::Deprecation`.
158
269
 
159
- * Fix arguments being destructed `Enumerable#many?` with block.
270
+ All usage of `ActiveSupport::Deprecation` as a singleton is deprecated, the most common one being
271
+ `ActiveSupport::Deprecation.warn`. Gem authors should now create their own deprecator (`ActiveSupport::Deprecation`
272
+ object), and use it to emit deprecation warnings.
160
273
 
161
- *Andrew Novoselac*
274
+ Calling any of the following without specifying a deprecator argument is also deprecated:
275
+ * Module.deprecate
276
+ * deprecate_constant
277
+ * DeprecatedObjectProxy
278
+ * DeprecatedInstanceVariableProxy
279
+ * DeprecatedConstantProxy
280
+ * deprecation-related test assertions
162
281
 
163
- * Fix humanize for strings ending with id.
282
+ Use of `ActiveSupport::Deprecation.silence` and configuration methods like `behavior=`, `disallowed_behavior=`,
283
+ `disallowed_warnings=` should now be aimed at the [application's deprecators](https://api.rubyonrails.org/classes/Rails/Application.html#method-i-deprecators).
164
284
 
165
- *fatkodima*
285
+ ```ruby
286
+ Rails.application.deprecators.silence do
287
+ # code that emits deprecation warnings
288
+ end
289
+ ```
166
290
 
291
+ If your gem has a Railtie or Engine, it's encouraged to add your deprecator to the application's deprecators, that
292
+ way the deprecation related configuration options will apply to it as well, e.g.
293
+ `config.active_support.report_deprecations` set to `false` in the production environment will also disable your
294
+ deprecator.
167
295
 
168
- ## Rails 7.0.5.1 (June 26, 2023) ##
296
+ ```ruby
297
+ initializer "my_gem.deprecator" do |app|
298
+ app.deprecators[:my_gem] = MyGem.deprecator
299
+ end
300
+ ```
169
301
 
170
- * No changes.
302
+ *Étienne Barrié*
171
303
 
304
+ * Add `Object#with` to set and restore public attributes around a block
172
305
 
173
- ## Rails 7.0.5 (May 24, 2023) ##
306
+ ```ruby
307
+ client.timeout # => 5
308
+ client.with(timeout: 1) do
309
+ client.timeout # => 1
310
+ end
311
+ client.timeout # => 5
312
+ ```
174
313
 
175
- * Fixes TimeWithZone ArgumentError.
314
+ *Jean Boussier*
176
315
 
177
- *Niklas Häusele*
316
+ * Remove deprecated support to generate incorrect RFC 4122 UUIDs when providing a namespace ID that is not one of the
317
+ constants defined on `Digest::UUID`.
178
318
 
319
+ *Rafael Mendonça França*
179
320
 
180
- ## Rails 7.0.4.3 (March 13, 2023) ##
321
+ * Deprecate `config.active_support.use_rfc4122_namespaced_uuids`.
181
322
 
182
- * Implement SafeBuffer#bytesplice
323
+ *Rafael Mendonça França*
183
324
 
184
- [CVE-2023-28120]
325
+ * Remove implicit conversion of objects into `String` by `ActiveSupport::SafeBuffer`.
185
326
 
327
+ *Rafael Mendonça França*
186
328
 
187
- ## Rails 7.0.4.2 (January 24, 2023) ##
329
+ * Remove deprecated `active_support/core_ext/range/include_time_with_zone` file.
188
330
 
189
- * No changes.
331
+ *Rafael Mendonça França*
190
332
 
333
+ * Deprecate `config.active_support.remove_deprecated_time_with_zone_name`.
191
334
 
192
- ## Rails 7.0.4.1 (January 17, 2023) ##
335
+ *Rafael Mendonça França*
193
336
 
194
- * Avoid regex backtracking in Inflector.underscore
337
+ * Remove deprecated override of `ActiveSupport::TimeWithZone.name`.
195
338
 
196
- [CVE-2023-22796]
339
+ *Rafael Mendonça França*
197
340
 
341
+ * Deprecate `config.active_support.disable_to_s_conversion`.
198
342
 
199
- ## Rails 7.0.4 (September 09, 2022) ##
343
+ *Rafael Mendonça França*
200
344
 
201
- * Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
345
+ * Remove deprecated option to passing a format to `#to_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
346
+ `BigDecimal`, `Float` and, `Integer`.
202
347
 
203
- Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
204
- process closed the read end, wrote to it, and then terminated (which
205
- presumably closed the file descriptors on its end). The parent process
206
- closed the write end, read from it, and returned, never closing the read
207
- end.
348
+ *Rafael Mendonça França*
208
349
 
209
- This resulted in an accumulation of open file descriptors, which could
210
- cause errors if the limit is reached.
350
+ * Remove deprecated `ActiveSupport::PerThreadRegistry`.
211
351
 
212
- *Sam Bostock*
352
+ *Rafael Mendonça França*
213
353
 
214
- * Redis cache store is now compatible with redis-rb 5.0.
354
+ * Remove deprecated override of `Enumerable#sum`.
215
355
 
216
- *Jean Boussier*
356
+ *Rafael Mendonça França*
217
357
 
218
- * Fix `NoMethodError` on custom `ActiveSupport::Deprecation` behavior.
358
+ * Deprecated initializing a `ActiveSupport::Cache::MemCacheStore` with an instance of `Dalli::Client`.
219
359
 
220
- `ActiveSupport::Deprecation.behavior=` was supposed to accept any object
221
- that responds to `call`, but in fact its internal implementation assumed that
222
- this object could respond to `arity`, so it was restricted to only `Proc` objects.
360
+ Deprecate the undocumented option of providing an already-initialized instance of `Dalli::Client` to `ActiveSupport::Cache::MemCacheStore`. Such clients could be configured with unrecognized options, which could lead to unexpected behavior. Instead, provide addresses as documented.
223
361
 
224
- This change removes this `arity` restriction of custom behaviors.
362
+ *aledustet*
225
363
 
226
- *Ryo Nakamura*
364
+ * Stub `Time.new()` in `TimeHelpers#travel_to`
227
365
 
366
+ ```ruby
367
+ travel_to Time.new(2004, 11, 24) do
368
+ # Inside the `travel_to` block `Time.new` is stubbed
369
+ assert_equal Time.new.year, 2004
370
+ end
371
+ ```
228
372
 
229
- ## Rails 7.0.3.1 (July 12, 2022) ##
373
+ *fatkodima*
230
374
 
231
- * No changes.
375
+ * Raise `ActiveSupport::MessageEncryptor::InvalidMessage` from
376
+ `ActiveSupport::MessageEncryptor#decrypt_and_verify` regardless of cipher.
377
+ Previously, when a `MessageEncryptor` was using a non-AEAD cipher such as
378
+ AES-256-CBC, a corrupt or tampered message would raise
379
+ `ActiveSupport::MessageVerifier::InvalidSignature`. Now, all ciphers raise
380
+ the same error:
381
+
382
+ ```ruby
383
+ encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-gcm")
384
+ message = encryptor.encrypt_and_sign("message")
385
+ encryptor.decrypt_and_verify(message.next)
386
+ # => raises ActiveSupport::MessageEncryptor::InvalidMessage
387
+
388
+ encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-cbc")
389
+ message = encryptor.encrypt_and_sign("message")
390
+ encryptor.decrypt_and_verify(message.next)
391
+ # BEFORE:
392
+ # => raises ActiveSupport::MessageVerifier::InvalidSignature
393
+ # AFTER:
394
+ # => raises ActiveSupport::MessageEncryptor::InvalidMessage
395
+ ```
232
396
 
397
+ *Jonathan Hefner*
233
398
 
234
- ## Rails 7.0.3 (May 09, 2022) ##
399
+ * Support `nil` original values when using `ActiveSupport::MessageVerifier#verify`.
400
+ Previously, `MessageVerifier#verify` did not work with `nil` original
401
+ values, though both `MessageVerifier#verified` and
402
+ `MessageEncryptor#decrypt_and_verify` do:
235
403
 
236
- * No changes.
404
+ ```ruby
405
+ encryptor = ActiveSupport::MessageEncryptor.new(secret)
406
+ message = encryptor.encrypt_and_sign(nil)
237
407
 
408
+ encryptor.decrypt_and_verify(message)
409
+ # => nil
238
410
 
239
- ## Rails 7.0.2.4 (April 26, 2022) ##
411
+ verifier = ActiveSupport::MessageVerifier.new(secret)
412
+ message = verifier.generate(nil)
240
413
 
241
- * Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
414
+ verifier.verified(message)
415
+ # => nil
242
416
 
243
- Add the method `ERB::Util.xml_name_escape` to escape dangerous characters
244
- in names of tags and names of attributes, following the specification of XML.
417
+ verifier.verify(message)
418
+ # BEFORE:
419
+ # => raises ActiveSupport::MessageVerifier::InvalidSignature
420
+ # AFTER:
421
+ # => nil
422
+ ```
245
423
 
246
- *Álvaro Martín Fraguas*
424
+ *Jonathan Hefner*
247
425
 
248
- ## Rails 7.0.2.3 (March 08, 2022) ##
426
+ * Maintain `html_safe?` on html_safe strings when sliced with `slice`, `slice!`, or `chr` method.
249
427
 
250
- * No changes.
428
+ Previously, `html_safe?` was only maintained when the html_safe strings were sliced
429
+ with `[]` method. Now, `slice`, `slice!`, and `chr` methods will maintain `html_safe?` like `[]` method.
251
430
 
431
+ ```ruby
432
+ string = "<div>test</div>".html_safe
433
+ string.slice(0, 1).html_safe? # => true
434
+ string.slice!(0, 1).html_safe? # => true
435
+ # maintain html_safe? after the slice!
436
+ string.html_safe? # => true
437
+ string.chr # => true
438
+ ```
252
439
 
253
- ## Rails 7.0.2.2 (February 11, 2022) ##
440
+ *Michael Go*
254
441
 
255
- * Fix Reloader method signature to work with the new Executor signature
442
+ * Add `Object#in?` support for open ranges.
256
443
 
444
+ ```ruby
445
+ assert Date.today.in?(..Date.tomorrow)
446
+ assert_not Date.today.in?(Date.tomorrow..)
447
+ ```
257
448
 
258
- ## Rails 7.0.2.1 (February 11, 2022) ##
449
+ *Ignacio Galindo*
259
450
 
260
- * No changes.
451
+ * `config.i18n.raise_on_missing_translations = true` now raises on any missing translation.
261
452
 
453
+ Previously it would only raise when called in a view or controller. Now it will raise
454
+ anytime `I18n.t` is provided an unrecognised key.
262
455
 
263
- ## Rails 7.0.2 (February 08, 2022) ##
456
+ If you do not want this behaviour, you can customise the i18n exception handler. See the
457
+ upgrading guide or i18n guide for more information.
264
458
 
265
- * Fix `ActiveSupport::EncryptedConfiguration` to be compatible with Psych 4
459
+ *Alex Ghiculescu*
266
460
 
267
- *Stephen Sugden*
461
+ * `ActiveSupport::CurrentAttributes` now raises if a restricted attribute name is used.
268
462
 
269
- * Improve `File.atomic_write` error handling.
463
+ Attributes such as `set` and `reset` cannot be used as they clash with the
464
+ `CurrentAttributes` public API.
270
465
 
271
- *Daniel Pepper*
466
+ *Alex Ghiculescu*
272
467
 
468
+ * `HashWithIndifferentAccess#transform_keys` now takes a Hash argument, just
469
+ as Ruby's `Hash#transform_keys` does.
273
470
 
274
- ## Rails 7.0.1 (January 06, 2022) ##
471
+ *Akira Matsuda*
275
472
 
276
- * Fix `Class#descendants` and `DescendantsTracker#descendants` compatibility with Ruby 3.1.
473
+ * `delegate` now defines method with proper arity when delegating to a Class.
474
+ With this change, it defines faster method (3.5x faster with no argument).
475
+ However, in order to gain this benefit, the delegation target method has to
476
+ be defined before declaring the delegation.
277
477
 
278
- [The native `Class#descendants` was reverted prior to Ruby 3.1 release](https://bugs.ruby-lang.org/issues/14394#note-33),
279
- but `Class#subclasses` was kept, breaking the feature detection.
478
+ ```ruby
479
+ # This defines 3.5 times faster method than before
480
+ class C
481
+ def self.x() end
482
+ delegate :x, to: :class
483
+ end
280
484
 
281
- *Jean Boussier*
485
+ class C
486
+ # This works but silently falls back to old behavior because
487
+ # `delegate` cannot find the definition of `x`
488
+ delegate :x, to: :class
489
+ def self.x() end
490
+ end
491
+ ```
282
492
 
493
+ *Akira Matsuda*
283
494
 
284
- ## Rails 7.0.0 (December 15, 2021) ##
495
+ * `assert_difference` message now includes what changed.
285
496
 
286
- * Fix `ActiveSupport::Duration.build` to support negative values.
497
+ This makes it easier to debug non-obvious failures.
287
498
 
288
- The algorithm to collect the `parts` of the `ActiveSupport::Duration`
289
- ignored the sign of the `value` and accumulated incorrect part values. This
290
- impacted `ActiveSupport::Duration#sum` (which is dependent on `parts`) but
291
- not `ActiveSupport::Duration#eql?` (which is dependent on `value`).
499
+ Before:
292
500
 
293
- *Caleb Buxton*, *Braden Staudacher*
501
+ ```
502
+ "User.count" didn't change by 32.
503
+ Expected: 1611
504
+ Actual: 1579
505
+ ```
294
506
 
507
+ After:
295
508
 
296
- ## Rails 7.0.0.rc3 (December 14, 2021) ##
509
+ ```
510
+ "User.count" didn't change by 32, but by 0.
511
+ Expected: 1611
512
+ Actual: 1579
513
+ ```
297
514
 
298
- * No changes.
515
+ *Alex Ghiculescu*
299
516
 
517
+ * Add ability to match exception messages to `assert_raises` assertion
300
518
 
301
- ## Rails 7.0.0.rc2 (December 14, 2021) ##
519
+ Instead of this
520
+ ```ruby
521
+ error = assert_raises(ArgumentError) do
522
+ perform_service(param: 'exception')
523
+ end
524
+ assert_match(/incorrect param/i, error.message)
525
+ ```
302
526
 
303
- * No changes.
527
+ you can now write this
528
+ ```ruby
529
+ assert_raises(ArgumentError, match: /incorrect param/i) do
530
+ perform_service(param: 'exception')
531
+ end
532
+ ```
304
533
 
305
- ## Rails 7.0.0.rc1 (December 06, 2021) ##
534
+ *fatkodima*
306
535
 
307
- * Deprecate passing a format to `#to_s` in favor of `#to_formatted_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
308
- `BigDecimal`, `Float` and, `Integer`.
536
+ * Add `Rails.env.local?` shorthand for `Rails.env.development? || Rails.env.test?`.
309
537
 
310
- *Rafael Mendonça França*
538
+ *DHH*
539
+
540
+ * `ActiveSupport::Testing::TimeHelpers` now accepts named `with_usec` argument
541
+ to `freeze_time`, `travel`, and `travel_to` methods. Passing true prevents
542
+ truncating the destination time with `change(usec: 0)`.
311
543
 
312
- * Document `ActiveSupport::Testing::Deprecation`.
544
+ *KevSlashNull*, and *serprex*
313
545
 
314
- *Sam Bostock & Sam Jordan*
546
+ * `ActiveSupport::CurrentAttributes.resets` now accepts a method name
315
547
 
316
- * Add `Pathname#existence`.
548
+ The block API is still the recommended approach, but now both APIs are supported:
317
549
 
318
550
  ```ruby
319
- Pathname.new("file").existence&.read
551
+ class Current < ActiveSupport::CurrentAttributes
552
+ resets { Time.zone = nil }
553
+ resets :clear_time_zone
554
+ end
320
555
  ```
321
556
 
322
- *Timo Schilling*
323
-
324
- * Remove deprecate `ActiveSupport::Multibyte::Unicode.default_normalization_form`.
325
-
326
- *Rafael Mendonça França*
327
-
328
- * Remove deprecated support to use `Range#include?` to check the inclusion of a value in
329
- a date time range is deprecated.
330
-
331
- *Rafael Mendonça França*
332
-
333
- * Remove deprecated `URI.parser`.
557
+ *Alex Ghiculescu*
334
558
 
335
- *Rafael Mendonça França*
559
+ * Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
336
560
 
337
- * Remove deprecated `config.active_support.use_sha1_digests`.
561
+ Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
562
+ process closed the read end, wrote to it, and then terminated (which
563
+ presumably closed the file descriptors on its end). The parent process
564
+ closed the write end, read from it, and returned, never closing the read
565
+ end.
338
566
 
339
- *Rafael Mendonça França*
567
+ This resulted in an accumulation of open file descriptors, which could
568
+ cause errors if the limit is reached.
340
569
 
341
- * Invoking `Object#with_options` without a `&block` argument returns the
342
- `ActiveSupport::OptionMerger` instance.
570
+ *Sam Bostock*
343
571
 
344
- *Sean Doyle*
572
+ * Fix `Time#change` and `Time#advance` for times around the end of Daylight
573
+ Saving Time.
345
574
 
346
- * `Rails.application.executor` hooks can now be called around every test
575
+ Previously, when `Time#change` or `Time#advance` constructed a time inside
576
+ the final stretch of Daylight Saving Time (DST), the non-DST offset would
577
+ always be chosen for local times:
347
578
 
348
- This helps to better simulate request or job local state being reset around tests and prevents state
349
- leaking from one test to another.
579
+ ```ruby
580
+ # DST ended just before 2021-11-07 2:00:00 AM in US/Eastern.
581
+ ENV["TZ"] = "US/Eastern"
582
+
583
+ time = Time.local(2021, 11, 07, 00, 59, 59) + 1
584
+ # => 2021-11-07 01:00:00 -0400
585
+ time.change(day: 07)
586
+ # => 2021-11-07 01:00:00 -0500
587
+ time.advance(seconds: 0)
588
+ # => 2021-11-07 01:00:00 -0500
589
+
590
+ time = Time.local(2021, 11, 06, 01, 00, 00)
591
+ # => 2021-11-06 01:00:00 -0400
592
+ time.change(day: 07)
593
+ # => 2021-11-07 01:00:00 -0500
594
+ time.advance(days: 1)
595
+ # => 2021-11-07 01:00:00 -0500
596
+ ```
350
597
 
351
- However it requires the executor hooks executed in the test environment to be re-entrant.
598
+ And the DST offset would always be chosen for times with a `TimeZone`
599
+ object:
352
600
 
353
- To enable this, set `config.active_support.executor_around_test_case = true` (this is the default in Rails 7).
601
+ ```ruby
602
+ Time.zone = "US/Eastern"
603
+
604
+ time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
605
+ # => 2021-11-07 01:00:00 -0500
606
+ time.change(day: 07)
607
+ # => 2021-11-07 01:00:00 -0400
608
+ time.advance(seconds: 0)
609
+ # => 2021-11-07 01:00:00 -0400
610
+
611
+ time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
612
+ # => 2021-11-08 01:00:00 -0500
613
+ time.change(day: 07)
614
+ # => 2021-11-07 01:00:00 -0400
615
+ time.advance(days: -1)
616
+ # => 2021-11-07 01:00:00 -0400
617
+ ```
354
618
 
355
- *Jean Boussier*
619
+ Now, `Time#change` and `Time#advance` will choose the offset that matches
620
+ the original time's offset when possible:
356
621
 
357
- * `ActiveSupport::DescendantsTracker` now mostly delegate to `Class#descendants` on Ruby 3.1
622
+ ```ruby
623
+ ENV["TZ"] = "US/Eastern"
624
+
625
+ time = Time.local(2021, 11, 07, 00, 59, 59) + 1
626
+ # => 2021-11-07 01:00:00 -0400
627
+ time.change(day: 07)
628
+ # => 2021-11-07 01:00:00 -0400
629
+ time.advance(seconds: 0)
630
+ # => 2021-11-07 01:00:00 -0400
631
+
632
+ time = Time.local(2021, 11, 06, 01, 00, 00)
633
+ # => 2021-11-06 01:00:00 -0400
634
+ time.change(day: 07)
635
+ # => 2021-11-07 01:00:00 -0400
636
+ time.advance(days: 1)
637
+ # => 2021-11-07 01:00:00 -0400
638
+
639
+ Time.zone = "US/Eastern"
640
+
641
+ time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
642
+ # => 2021-11-07 01:00:00 -0500
643
+ time.change(day: 07)
644
+ # => 2021-11-07 01:00:00 -0500
645
+ time.advance(seconds: 0)
646
+ # => 2021-11-07 01:00:00 -0500
647
+
648
+ time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
649
+ # => 2021-11-08 01:00:00 -0500
650
+ time.change(day: 07)
651
+ # => 2021-11-07 01:00:00 -0500
652
+ time.advance(days: -1)
653
+ # => 2021-11-07 01:00:00 -0500
654
+ ```
358
655
 
359
- Ruby now provides a fast `Class#descendants` making `ActiveSupport::DescendantsTracker` mostly useless.
656
+ *Kevin Hall*, *Takayoshi Nishida*, and *Jonathan Hefner*
360
657
 
361
- As a result the following methods are deprecated:
658
+ * Fix MemoryStore to preserve entries TTL when incrementing or decrementing
362
659
 
363
- - `ActiveSupport::DescendantsTracker.direct_descendants`
364
- - `ActiveSupport::DescendantsTracker#direct_descendants`
660
+ This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.
365
661
 
366
662
  *Jean Boussier*
367
663
 
368
- * Fix the `Digest::UUID.uuid_from_hash` behavior for namespace IDs that are different from the ones defined on `Digest::UUID`.
369
-
370
- The new behavior will be enabled by setting the
371
- `config.active_support.use_rfc4122_namespaced_uuids` option to `true`
372
- and is the default for new apps.
664
+ * `Rails.error.handle` and `Rails.error.record` filter now by multiple error classes.
373
665
 
374
- The old behavior is the default for upgraded apps and will output a
375
- deprecation warning every time a value that is different than one of
376
- the constants defined on the `Digest::UUID` extension is used as the
377
- namespace ID.
666
+ ```ruby
667
+ Rails.error.handle(IOError, ArgumentError) do
668
+ 1 + '1' # raises TypeError
669
+ end
670
+ 1 + 1 # TypeErrors are not IOErrors or ArgumentError, so this will *not* be handled
671
+ ```
378
672
 
379
- *Alex Robbin*, *Erich Soares Machado*, *Eugene Kenny*
673
+ *Martin Spickermann*
380
674
 
381
- * `ActiveSupport::Inflector::Inflections#clear(:acronyms)` is now supported,
382
- and `inflector.clear` / `inflector.clear(:all)` also clears acronyms.
675
+ * `Class#subclasses` and `Class#descendants` now automatically filter reloaded classes.
383
676
 
384
- *Alex Ghiculescu*, *Oliver Peate*
677
+ Previously they could return old implementations of reloadable classes that have been
678
+ dereferenced but not yet garbage collected.
385
679
 
680
+ They now automatically filter such classes like `DescendantTracker#subclasses` and
681
+ `DescendantTracker#descendants`.
386
682
 
387
- ## Rails 7.0.0.alpha2 (September 15, 2021) ##
683
+ *Jean Boussier*
388
684
 
389
- * No changes.
685
+ * `Rails.error.report` now marks errors as reported to avoid reporting them twice.
390
686
 
687
+ In some cases, users might want to report errors explicitly with some extra context
688
+ before letting it bubble up.
391
689
 
392
- ## Rails 7.0.0.alpha1 (September 15, 2021) ##
690
+ This also allows to safely catch and report errors outside of the execution context.
393
691
 
394
- * `ActiveSupport::Dependencies` no longer installs a `const_missing` hook. Before this, you could push to the autoload paths and have constants autoloaded. This feature, known as the `classic` autoloader, has been removed.
692
+ *Jean Boussier*
395
693
 
396
- *Xavier Noria*
694
+ * Add `assert_error_reported` and `assert_no_error_reported`
397
695
 
398
- * Private internal classes of `ActiveSupport::Dependencies` have been deleted, like `ActiveSupport::Dependencies::Reference`, `ActiveSupport::Dependencies::Blamable`, and others.
696
+ Allows to easily asserts an error happened but was handled
399
697
 
400
- *Xavier Noria*
698
+ ```ruby
699
+ report = assert_error_reported(IOError) do
700
+ # ...
701
+ end
702
+ assert_equal "Oops", report.error.message
703
+ assert_equal "admin", report.context[:section]
704
+ assert_equal :warning, report.severity
705
+ assert_predicate report, :handled?
706
+ ```
401
707
 
402
- * The private API of `ActiveSupport::Dependencies` has been deleted. That includes methods like `hook!`, `unhook!`, `depend_on`, `require_or_load`, `mechanism`, and many others.
708
+ *Jean Boussier*
403
709
 
404
- *Xavier Noria*
710
+ * `ActiveSupport::Deprecation` behavior callbacks can now receive the
711
+ deprecator instance as an argument. This makes it easier for such callbacks
712
+ to change their behavior based on the deprecator's state. For example,
713
+ based on the deprecator's `debug` flag.
405
714
 
406
- * Improves the performance of `ActiveSupport::NumberHelper` formatters by avoiding the use of exceptions as flow control.
715
+ 3-arity and splat-args callbacks such as the following will now be passed
716
+ the deprecator instance as their third argument:
407
717
 
408
- *Mike Dalessio*
718
+ * `->(message, callstack, deprecator) { ... }`
719
+ * `->(*args) { ... }`
720
+ * `->(message, *other_args) { ... }`
409
721
 
410
- * Removed rescue block from `ActiveSupport::Cache::RedisCacheStore#handle_exception`
722
+ 2-arity and 4-arity callbacks such as the following will continue to behave
723
+ the same as before:
411
724
 
412
- Previously, if you provided a `error_handler` to `redis_cache_store`, any errors thrown by
413
- the error handler would be rescued and logged only. Removed the `rescue` clause from `handle_exception`
414
- to allow these to be thrown.
725
+ * `->(message, callstack) { ... }`
726
+ * `->(message, callstack, deprecation_horizon, gem_name) { ... }`
727
+ * `->(message, callstack, *deprecation_details) { ... }`
415
728
 
416
- *Nicholas A. Stuart*
729
+ *Jonathan Hefner*
417
730
 
418
- * Allow entirely opting out of deprecation warnings.
731
+ * `ActiveSupport::Deprecation#disallowed_warnings` now affects the instance on
732
+ which it is configured.
419
733
 
420
- Previously if you did `app.config.active_support.deprecation = :silence`, some work would
421
- still be done on each call to `ActiveSupport::Deprecation.warn`. In very hot paths, this could
422
- cause performance issues.
734
+ This means that individual `ActiveSupport::Deprecation` instances can be
735
+ configured with their own disallowed warnings, and the global
736
+ `ActiveSupport::Deprecation.disallowed_warnings` now only affects the global
737
+ `ActiveSupport::Deprecation.warn`.
423
738
 
424
- Now, you can make `ActiveSupport::Deprecation.warn` a no-op:
739
+ **Before**
425
740
 
426
741
  ```ruby
427
- config.active_support.report_deprecations = false
742
+ ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
743
+ deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
744
+ deprecator.disallowed_warnings = ["bar"]
745
+
746
+ ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
747
+ ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
748
+ deprecator.warn("foo") # => raise ActiveSupport::DeprecationException
749
+ deprecator.warn("bar") # => print "DEPRECATION WARNING: bar"
428
750
  ```
429
751
 
430
- This is the default in production for new apps. It is the equivalent to:
752
+ **After**
431
753
 
432
754
  ```ruby
433
- config.active_support.deprecation = :silence
434
- config.active_support.disallowed_deprecation = :silence
755
+ ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
756
+ deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
757
+ deprecator.disallowed_warnings = ["bar"]
758
+
759
+ ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
760
+ ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
761
+ deprecator.warn("foo") # => print "DEPRECATION WARNING: foo"
762
+ deprecator.warn("bar") # => raise ActiveSupport::DeprecationException
435
763
  ```
436
764
 
437
- but will take a more optimised code path.
765
+ Note that global `ActiveSupport::Deprecation` methods such as `ActiveSupport::Deprecation.warn`
766
+ and `ActiveSupport::Deprecation.disallowed_warnings` have been deprecated.
438
767
 
439
- *Alex Ghiculescu*
440
-
441
- * Faster tests by parallelizing only when overhead is justified by the number
442
- of them.
768
+ *Jonathan Hefner*
443
769
 
444
- Running tests in parallel adds overhead in terms of database
445
- setup and fixture loading. Now, Rails will only parallelize test executions when
446
- there are enough tests to make it worth it.
770
+ * Add italic and underline support to `ActiveSupport::LogSubscriber#color`
447
771
 
448
- This threshold is 50 by default, and is configurable via config setting in
449
- your test.rb:
772
+ Previously, only bold text was supported via a positional argument.
773
+ This allows for bold, italic, and underline options to be specified
774
+ for colored logs.
450
775
 
451
776
  ```ruby
452
- config.active_support.test_parallelization_threshold = 100
777
+ info color("Hello world!", :red, bold: true, underline: true)
453
778
  ```
454
779
 
455
- It's also configurable at the test case level:
456
-
457
- ```ruby
458
- class ActiveSupport::TestCase
459
- parallelize threshold: 100
460
- end
461
- ```
780
+ *Gannon McGibbon*
462
781
 
463
- *Jorge Manrubia*
782
+ * Add `String#downcase_first` method.
464
783
 
465
- * OpenSSL constants are now used for Digest computations.
784
+ This method is the corollary of `String#upcase_first`.
466
785
 
467
- *Dirkjan Bussink*
786
+ *Mark Schneider*
468
787
 
469
- * `TimeZone.iso8601` now accepts valid ordinal values similar to Ruby's `Date._iso8601` method.
470
- A valid ordinal value will be converted to an instance of `TimeWithZone` using the `:year`
471
- and `:yday` fragments returned from `Date._iso8601`.
788
+ * `thread_mattr_accessor` will call `.dup.freeze` on non-frozen default values.
472
789
 
473
- ```ruby
474
- twz = ActiveSupport::TimeZone["Eastern Time (US & Canada)"].iso8601("21087")
475
- twz.to_a[0, 6] == [0, 0, 0, 28, 03, 2021]
476
- ```
790
+ This provides a basic level of protection against different threads trying
791
+ to mutate a shared default object.
477
792
 
478
- *Steve Laing*
793
+ *Jonathan Hefner*
479
794
 
480
- * `Time#change` and methods that call it (e.g. `Time#advance`) will now
481
- return a `Time` with the timezone argument provided, if the caller was
482
- initialized with a timezone argument.
795
+ * Add `raise_on_invalid_cache_expiration_time` config to `ActiveSupport::Cache::Store`
483
796
 
484
- Fixes [#42467](https://github.com/rails/rails/issues/42467).
797
+ Specifies if an `ArgumentError` should be raised if `Rails.cache` `fetch` or
798
+ `write` are given an invalid `expires_at` or `expires_in` time.
485
799
 
486
- *Alex Ghiculescu*
800
+ Options are `true`, and `false`. If `false`, the exception will be reported
801
+ as `handled` and logged instead. Defaults to `true` if `config.load_defaults >= 7.1`.
487
802
 
488
- * Allow serializing any module or class to JSON by name.
803
+ *Trevor Turk*
489
804
 
490
- *Tyler Rick*, *Zachary Scott*
805
+ * `ActiveSupport::Cache:Store#fetch` now passes an options accessor to the block.
491
806
 
492
- * Raise `ActiveSupport::EncryptedFile::MissingKeyError` when the
493
- `RAILS_MASTER_KEY` environment variable is blank (e.g. `""`).
807
+ It makes possible to override cache options:
494
808
 
495
- *Sunny Ripert*
809
+ Rails.cache.fetch("3rd-party-token") do |name, options|
810
+ token = fetch_token_from_remote
811
+ # set cache's TTL to match token's TTL
812
+ options.expires_in = token.expires_in
813
+ token
814
+ end
496
815
 
497
- * The `from:` option is added to `ActiveSupport::TestCase#assert_no_changes`.
816
+ *Andrii Gladkyi*, *Jean Boussier*
498
817
 
499
- It permits asserting on the initial value that is expected not to change.
818
+ * `default` option of `thread_mattr_accessor` now applies through inheritance and
819
+ also across new threads.
500
820
 
501
- ```ruby
502
- assert_no_changes -> { Status.all_good? }, from: true do
503
- post :create, params: { status: { ok: true } }
504
- end
505
- ```
821
+ Previously, the `default` value provided was set only at the moment of defining
822
+ the attribute writer, which would cause the attribute to be uninitialized in
823
+ descendants and in other threads.
506
824
 
507
- *George Claghorn*
825
+ Fixes #43312.
508
826
 
509
- * Deprecate `ActiveSupport::SafeBuffer`'s incorrect implicit conversion of objects into string.
827
+ *Thierry Deo*
510
828
 
511
- Except for a few methods like `String#%`, objects must implement `#to_str`
512
- to be implicitly converted to a String in string operations. In some
513
- circumstances `ActiveSupport::SafeBuffer` was incorrectly calling the
514
- explicit conversion method (`#to_s`) on them. This behavior is now
515
- deprecated.
829
+ * Redis cache store is now compatible with redis-rb 5.0.
516
830
 
517
831
  *Jean Boussier*
518
832
 
519
- * Allow nested access to keys on `Rails.application.credentials`.
833
+ * Add `skip_nil:` support to `ActiveSupport::Cache::Store#fetch_multi`.
520
834
 
521
- Previously only top level keys in `credentials.yml.enc` could be accessed with method calls. Now any key can.
835
+ *Daniel Alfaro*
522
836
 
523
- For example, given these secrets:
837
+ * Add `quarter` method to date/time
524
838
 
525
- ```yml
526
- aws:
527
- access_key_id: 123
528
- secret_access_key: 345
529
- ```
839
+ *Matt Swanson*
530
840
 
531
- `Rails.application.credentials.aws.access_key_id` will now return the same thing as
532
- `Rails.application.credentials.aws[:access_key_id]`.
841
+ * Fix `NoMethodError` on custom `ActiveSupport::Deprecation` behavior.
533
842
 
534
- *Alex Ghiculescu*
843
+ `ActiveSupport::Deprecation.behavior=` was supposed to accept any object
844
+ that responds to `call`, but in fact its internal implementation assumed that
845
+ this object could respond to `arity`, so it was restricted to only `Proc` objects.
535
846
 
536
- * Added a faster and more compact `ActiveSupport::Cache` serialization format.
847
+ This change removes this `arity` restriction of custom behaviors.
537
848
 
538
- It can be enabled with `config.active_support.cache_format_version = 7.0` or
539
- `config.load_defaults 7.0`. Regardless of the configuration Active Support
540
- 7.0 can read cache entries serialized by Active Support 6.1 which allows to
541
- upgrade without invalidating the cache. However Rails 6.1 can't read the
542
- new format, so all readers must be upgraded before the new format is enabled.
849
+ *Ryo Nakamura*
543
850
 
544
- *Jean Boussier*
851
+ * Support `:url_safe` option for `MessageEncryptor`.
545
852
 
546
- * Add `Enumerable#sole`, per `ActiveRecord::FinderMethods#sole`. Returns the
547
- sole item of the enumerable, raising if no items are found, or if more than
548
- one is.
853
+ The `MessageEncryptor` constructor now accepts a `:url_safe` option, similar
854
+ to the `MessageVerifier` constructor. When enabled, this option ensures
855
+ that messages use a URL-safe encoding.
549
856
 
550
- *Asherah Connor*
857
+ *Jonathan Hefner*
551
858
 
552
- * Freeze `ActiveSupport::Duration#parts` and remove writer methods.
859
+ * Add `url_safe` option to `ActiveSupport::MessageVerifier` initializer
553
860
 
554
- Durations are meant to be value objects and should not be mutated.
861
+ `ActiveSupport::MessageVerifier.new` now takes optional `url_safe` argument.
862
+ It can generate URL-safe strings by passing `url_safe: true`.
555
863
 
556
- *Andrew White*
864
+ ```ruby
865
+ verifier = ActiveSupport::MessageVerifier.new(url_safe: true)
866
+ message = verifier.generate(data) # => URL-safe string
867
+ ```
557
868
 
558
- * Fix `ActiveSupport::TimeZone#utc_to_local` with fractional seconds.
869
+ This option is `false` by default to be backwards compatible.
559
870
 
560
- When `utc_to_local_returns_utc_offset_times` is false and the time
561
- instance had fractional seconds the new UTC time instance was out by
562
- a factor of 1,000,000 as the `Time.utc` constructor takes a usec
563
- value and not a fractional second value.
871
+ *Shouichi Kamiya*
564
872
 
565
- *Andrew White*
873
+ * Enable connection pooling by default for `MemCacheStore` and `RedisCacheStore`.
566
874
 
567
- * Add `expires_at` argument to `ActiveSupport::Cache` `write` and `fetch` to set a cache entry TTL as an absolute time.
875
+ If you want to disable connection pooling, set `:pool` option to `false` when configuring the cache store:
568
876
 
569
877
  ```ruby
570
- Rails.cache.write(key, value, expires_at: Time.now.at_end_of_hour)
878
+ config.cache_store = :mem_cache_store, "cache.example.com", pool: false
571
879
  ```
572
880
 
573
- *Jean Boussier*
881
+ *fatkodima*
574
882
 
575
- * Deprecate `ActiveSupport::TimeWithZone.name` so that from Rails 7.1 it will use the default implementation.
883
+ * Add `force:` support to `ActiveSupport::Cache::Store#fetch_multi`.
576
884
 
577
- *Andrew White*
885
+ *fatkodima*
578
886
 
579
- * Deprecates Rails custom `Enumerable#sum` and `Array#sum` in favor of Ruby's native implementation which
580
- is considerably faster.
887
+ * Deprecated `:pool_size` and `:pool_timeout` options for configuring connection pooling in cache stores.
581
888
 
582
- Ruby requires an initializer for non-numeric type as per examples below:
889
+ Use `pool: true` to enable pooling with default settings:
583
890
 
584
891
  ```ruby
585
- %w[foo bar].sum('')
586
- # instead of %w[foo bar].sum
892
+ config.cache_store = :redis_cache_store, pool: true
893
+ ```
587
894
 
588
- [[1, 2], [3, 4, 5]].sum([])
589
- # instead of [[1, 2], [3, 4, 5]].sum
895
+ Or pass individual options via `:pool` option:
896
+
897
+ ```ruby
898
+ config.cache_store = :redis_cache_store, pool: { size: 10, timeout: 2 }
590
899
  ```
591
900
 
592
- *Alberto Mota*
901
+ *fatkodima*
902
+
903
+ * Allow #increment and #decrement methods of `ActiveSupport::Cache::Store`
904
+ subclasses to set new values.
593
905
 
594
- * Tests parallelization is now disabled when running individual files to prevent the setup overhead.
906
+ Previously incrementing or decrementing an unset key would fail and return
907
+ nil. A default will now be assumed and the key will be created.
595
908
 
596
- It can still be enforced if the environment variable `PARALLEL_WORKERS` is present and set to a value greater than 1.
909
+ *Andrej Blagojević*, *Eugene Kenny*
597
910
 
598
- *Ricardo Díaz*
911
+ * Add `skip_nil:` support to `RedisCacheStore`
599
912
 
600
- * Fix proxying keyword arguments in `ActiveSupport::CurrentAttributes`.
913
+ *Joey Paris*
601
914
 
602
- *Marcin Kołodziej*
915
+ * `ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true)` now
916
+ correctly writes expired keys.
603
917
 
604
- * Add `Enumerable#maximum` and `Enumerable#minimum` to easily calculate the maximum or minimum from extracted
605
- elements of an enumerable.
918
+ *Alan Savage*
606
919
 
607
- ```ruby
608
- payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
920
+ * `ActiveSupport::ErrorReporter` now accepts and forward a `source:` parameter.
609
921
 
610
- payments.minimum(:price) # => 5
611
- payments.maximum(:price) # => 15
612
- ```
922
+ This allow libraries to signal the origin of the errors, and reporters
923
+ to easily ignore some sources.
613
924
 
614
- This also allows passing enumerables to `fresh_when` and `stale?` in Action Controller.
615
- See PR [#41404](https://github.com/rails/rails/pull/41404) for an example.
925
+ *Jean Boussier*
616
926
 
617
- *Ayrton De Craene*
927
+ * Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
618
928
 
619
- * `ActiveSupport::Cache::MemCacheStore` now accepts an explicit `nil` for its `addresses` argument.
929
+ Add the method `ERB::Util.xml_name_escape` to escape dangerous characters
930
+ in names of tags and names of attributes, following the specification of XML.
620
931
 
621
- ```ruby
622
- config.cache_store = :mem_cache_store, nil
932
+ *Álvaro Martín Fraguas*
623
933
 
624
- # is now equivalent to
934
+ * Respect `ActiveSupport::Logger.new`'s `:formatter` keyword argument
625
935
 
626
- config.cache_store = :mem_cache_store
936
+ The stdlib `Logger::new` allows passing a `:formatter` keyword argument to
937
+ set the logger's formatter. Previously `ActiveSupport::Logger.new` ignored
938
+ that argument by always setting the formatter to an instance of
939
+ `ActiveSupport::Logger::SimpleFormatter`.
627
940
 
628
- # and is also equivalent to
941
+ *Steven Harman*
629
942
 
630
- config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"
943
+ * Deprecate preserving the pre-Ruby 2.4 behavior of `to_time`
631
944
 
632
- # which is the fallback behavior of Dalli
633
- ```
945
+ With Ruby 2.4+ the default for +to_time+ changed from converting to the
946
+ local system time to preserving the offset of the receiver. At the time Rails
947
+ supported older versions of Ruby so a compatibility layer was added to assist
948
+ in the migration process. From Rails 5.0 new applications have defaulted to
949
+ the Ruby 2.4+ behavior and since Rails 7.0 now only supports Ruby 2.7+
950
+ this compatibility layer can be safely removed.
634
951
 
635
- This helps those migrating from `:dalli_store`, where an explicit `nil` was permitted.
952
+ To minimize any noise generated the deprecation warning only appears when the
953
+ setting is configured to `false` as that is the only scenario where the
954
+ removal of the compatibility layer has any effect.
636
955
 
637
- *Michael Overmeyer*
956
+ *Andrew White*
638
957
 
639
- * Add `Enumerable#in_order_of` to put an Enumerable in a certain order by a key.
958
+ * `Pathname.blank?` only returns true for `Pathname.new("")`
640
959
 
641
- *DHH*
960
+ Previously it would end up calling `Pathname#empty?` which returned true
961
+ if the path existed and was an empty directory or file.
642
962
 
643
- * `ActiveSupport::Inflector.camelize` behaves expected when provided a symbol `:upper` or `:lower` argument. Matches
644
- `String#camelize` behavior.
963
+ That behavior was unlikely to be expected.
645
964
 
646
- *Alex Ghiculescu*
965
+ *Jean Boussier*
966
+
967
+ * Deprecate `Notification::Event`'s `#children` and `#parent_of?`
647
968
 
648
- * Raises an `ArgumentError` when the first argument of `ActiveSupport::Notification.subscribe` is
649
- invalid.
969
+ *John Hawthorn*
650
970
 
651
- *Vipul A M*
971
+ * Change the default serializer of `ActiveSupport::MessageVerifier` from
972
+ `Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
652
973
 
653
- * `HashWithIndifferentAccess#deep_transform_keys` now returns a `HashWithIndifferentAccess` instead of a `Hash`.
974
+ Messages serialized with `Marshal` can still be read, but new messages will
975
+ be serialized with `ActiveSupport::JSON`. For more information, see
976
+ https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
654
977
 
655
- *Nathaniel Woodthorpe*
978
+ *Saba Kiaei*, *David Buckley*, and *Jonathan Hefner*
656
979
 
657
- * Consume dalli’s `cache_nils` configuration as `ActiveSupport::Cache`'s `skip_nil` when using `MemCacheStore`.
980
+ * Change the default serializer of `ActiveSupport::MessageEncryptor` from
981
+ `Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
658
982
 
659
- *Ritikesh G*
983
+ Messages serialized with `Marshal` can still be read, but new messages will
984
+ be serialized with `ActiveSupport::JSON`. For more information, see
985
+ https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
660
986
 
661
- * Add `RedisCacheStore#stats` method similar to `MemCacheStore#stats`. Calls `redis#info` internally.
987
+ *Zack Deveau*, *Martin Gingras*, and *Jonathan Hefner*
662
988
 
663
- *Ritikesh G*
989
+ * Add `ActiveSupport::TestCase#stub_const` to stub a constant for the duration of a yield.
664
990
 
991
+ *DHH*
992
+
993
+ * Fix `ActiveSupport::EncryptedConfiguration` to be compatible with Psych 4
994
+
995
+ *Stephen Sugden*
996
+
997
+ * Improve `File.atomic_write` error handling
998
+
999
+ *Daniel Pepper*
1000
+
1001
+ * Fix `Class#descendants` and `DescendantsTracker#descendants` compatibility with Ruby 3.1.
1002
+
1003
+ [The native `Class#descendants` was reverted prior to Ruby 3.1 release](https://bugs.ruby-lang.org/issues/14394#note-33),
1004
+ but `Class#subclasses` was kept, breaking the feature detection.
1005
+
1006
+ *Jean Boussier*
665
1007
 
666
- Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activesupport/CHANGELOG.md) for previous changes.
1008
+ Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activesupport/CHANGELOG.md) for previous changes.