activesupport 7.0.7.2 → 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 (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +742 -285
  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 +36 -9
  13. data/lib/active_support/cache/mem_cache_store.rb +84 -68
  14. data/lib/active_support/cache/memory_store.rb +76 -24
  15. data/lib/active_support/cache/null_store.rb +6 -0
  16. data/lib/active_support/cache/redis_cache_store.rb +128 -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/subclasses.rb +13 -10
  28. data/lib/active_support/core_ext/date/conversions.rb +1 -0
  29. data/lib/active_support/core_ext/date.rb +0 -1
  30. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  31. data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
  32. data/lib/active_support/core_ext/date_time.rb +0 -1
  33. data/lib/active_support/core_ext/digest/uuid.rb +1 -10
  34. data/lib/active_support/core_ext/enumerable.rb +3 -75
  35. data/lib/active_support/core_ext/erb/util.rb +196 -0
  36. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  37. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  38. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  39. data/lib/active_support/core_ext/module/delegation.rb +40 -11
  40. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  41. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  42. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  43. data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
  44. data/lib/active_support/core_ext/numeric.rb +0 -1
  45. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  46. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  47. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  48. data/lib/active_support/core_ext/object/json.rb +10 -2
  49. data/lib/active_support/core_ext/object/with.rb +44 -0
  50. data/lib/active_support/core_ext/object/with_options.rb +3 -3
  51. data/lib/active_support/core_ext/object.rb +1 -0
  52. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  53. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  54. data/lib/active_support/core_ext/pathname.rb +1 -0
  55. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  56. data/lib/active_support/core_ext/range/{overlaps.rb → overlap.rb} +5 -3
  57. data/lib/active_support/core_ext/range.rb +1 -2
  58. data/lib/active_support/core_ext/securerandom.rb +24 -12
  59. data/lib/active_support/core_ext/string/filters.rb +20 -14
  60. data/lib/active_support/core_ext/string/inflections.rb +16 -5
  61. data/lib/active_support/core_ext/string/output_safety.rb +38 -174
  62. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  63. data/lib/active_support/core_ext/time/calculations.rb +18 -2
  64. data/lib/active_support/core_ext/time/conversions.rb +2 -2
  65. data/lib/active_support/core_ext/time/zones.rb +4 -4
  66. data/lib/active_support/core_ext/time.rb +0 -1
  67. data/lib/active_support/current_attributes.rb +15 -6
  68. data/lib/active_support/dependencies/autoload.rb +17 -12
  69. data/lib/active_support/deprecation/behaviors.rb +53 -32
  70. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  71. data/lib/active_support/deprecation/deprecators.rb +104 -0
  72. data/lib/active_support/deprecation/disallowed.rb +3 -5
  73. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  74. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  75. data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
  76. data/lib/active_support/deprecation/reporting.rb +35 -21
  77. data/lib/active_support/deprecation.rb +32 -5
  78. data/lib/active_support/deprecator.rb +7 -0
  79. data/lib/active_support/descendants_tracker.rb +104 -132
  80. data/lib/active_support/duration/iso8601_serializer.rb +0 -2
  81. data/lib/active_support/duration.rb +2 -1
  82. data/lib/active_support/encrypted_configuration.rb +30 -9
  83. data/lib/active_support/encrypted_file.rb +8 -3
  84. data/lib/active_support/environment_inquirer.rb +22 -2
  85. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  86. data/lib/active_support/error_reporter.rb +121 -35
  87. data/lib/active_support/execution_wrapper.rb +4 -4
  88. data/lib/active_support/file_update_checker.rb +4 -2
  89. data/lib/active_support/fork_tracker.rb +10 -2
  90. data/lib/active_support/gem_version.rb +4 -4
  91. data/lib/active_support/gzip.rb +2 -0
  92. data/lib/active_support/hash_with_indifferent_access.rb +35 -17
  93. data/lib/active_support/i18n.rb +1 -1
  94. data/lib/active_support/i18n_railtie.rb +20 -13
  95. data/lib/active_support/inflector/inflections.rb +2 -0
  96. data/lib/active_support/inflector/methods.rb +22 -10
  97. data/lib/active_support/inflector/transliterate.rb +3 -1
  98. data/lib/active_support/isolated_execution_state.rb +26 -22
  99. data/lib/active_support/json/decoding.rb +2 -1
  100. data/lib/active_support/json/encoding.rb +25 -43
  101. data/lib/active_support/key_generator.rb +9 -1
  102. data/lib/active_support/lazy_load_hooks.rb +6 -4
  103. data/lib/active_support/locale/en.yml +2 -0
  104. data/lib/active_support/log_subscriber.rb +78 -33
  105. data/lib/active_support/logger.rb +1 -1
  106. data/lib/active_support/logger_thread_safe_level.rb +9 -21
  107. data/lib/active_support/message_encryptor.rb +197 -53
  108. data/lib/active_support/message_encryptors.rb +140 -0
  109. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  110. data/lib/active_support/message_pack/extensions.rb +292 -0
  111. data/lib/active_support/message_pack/serializer.rb +63 -0
  112. data/lib/active_support/message_pack.rb +50 -0
  113. data/lib/active_support/message_verifier.rb +212 -93
  114. data/lib/active_support/message_verifiers.rb +134 -0
  115. data/lib/active_support/messages/codec.rb +65 -0
  116. data/lib/active_support/messages/metadata.rb +111 -45
  117. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  118. data/lib/active_support/messages/rotator.rb +34 -32
  119. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  120. data/lib/active_support/multibyte/chars.rb +2 -0
  121. data/lib/active_support/multibyte/unicode.rb +9 -37
  122. data/lib/active_support/notifications/fanout.rb +239 -81
  123. data/lib/active_support/notifications/instrumenter.rb +71 -14
  124. data/lib/active_support/notifications.rb +1 -1
  125. data/lib/active_support/number_helper/number_converter.rb +2 -2
  126. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  127. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  128. data/lib/active_support/ordered_hash.rb +3 -3
  129. data/lib/active_support/ordered_options.rb +14 -0
  130. data/lib/active_support/parameter_filter.rb +84 -69
  131. data/lib/active_support/proxy_object.rb +2 -0
  132. data/lib/active_support/railtie.rb +33 -21
  133. data/lib/active_support/reloader.rb +12 -4
  134. data/lib/active_support/rescuable.rb +2 -0
  135. data/lib/active_support/secure_compare_rotator.rb +16 -9
  136. data/lib/active_support/string_inquirer.rb +3 -1
  137. data/lib/active_support/subscriber.rb +9 -27
  138. data/lib/active_support/syntax_error_proxy.rb +49 -0
  139. data/lib/active_support/tagged_logging.rb +60 -24
  140. data/lib/active_support/test_case.rb +153 -6
  141. data/lib/active_support/testing/assertions.rb +25 -9
  142. data/lib/active_support/testing/autorun.rb +0 -2
  143. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  144. data/lib/active_support/testing/deprecation.rb +25 -25
  145. data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
  146. data/lib/active_support/testing/isolation.rb +1 -1
  147. data/lib/active_support/testing/method_call_assertions.rb +21 -8
  148. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  149. data/lib/active_support/testing/stream.rb +1 -1
  150. data/lib/active_support/testing/strict_warnings.rb +38 -0
  151. data/lib/active_support/testing/time_helpers.rb +32 -14
  152. data/lib/active_support/time_with_zone.rb +6 -42
  153. data/lib/active_support/values/time_zone.rb +9 -7
  154. data/lib/active_support/version.rb +1 -1
  155. data/lib/active_support/xml_mini/jdom.rb +3 -10
  156. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  157. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  158. data/lib/active_support/xml_mini/rexml.rb +1 -1
  159. data/lib/active_support/xml_mini.rb +2 -2
  160. data/lib/active_support.rb +13 -3
  161. metadata +103 -18
  162. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  163. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -37
  164. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -33
  165. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  166. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -33
  167. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
  168. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -33
  169. data/lib/active_support/core_ext/uri.rb +0 -5
  170. data/lib/active_support/per_thread_registry.rb +0 -65
data/CHANGELOG.md CHANGED
@@ -1,551 +1,1008 @@
1
- ## Rails 7.0.7.2 (August 22, 2023) ##
1
+ ## Rails 7.1.0.beta1 (September 13, 2023) ##
2
2
 
3
- * No changes.
3
+ * Add `drb`, `mutex_m` and `base64` that are bundled gem candidates for Ruby 3.4
4
4
 
5
+ *Yasuo Honda*
5
6
 
6
- ## Rails 7.0.7.1 (August 22, 2023) ##
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.
7
10
 
8
- * Use a temporary file for storing unencrypted files while editing
11
+ *Jonathan Hefner*
9
12
 
10
- [CVE-2023-38037]
13
+ * Make all cache stores return a boolean for `#delete`
11
14
 
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.
12
18
 
13
- ## Rails 7.0.7 (August 09, 2023) ##
19
+ The `FileStore` would return `nil` if the entry doesn't exists and returns
20
+ `false` now as well.
14
21
 
15
- * Fix `Cache::NullStore` with local caching for repeated reads.
22
+ *Petrik de Heus*
16
23
 
17
- *fatkodima*
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:
18
27
 
19
- * Fix `to_s` with no arguments not respecting custom `:default` formats
28
+ ```ruby
29
+ module MyCompressor
30
+ def self.deflate(string)
31
+ # compression logic...
32
+ end
20
33
 
21
- *Hartley McGuire*
34
+ def self.inflate(compressed)
35
+ # decompression logic...
36
+ end
37
+ end
38
+
39
+ config.cache_store = :redis_cache_store, { compressor: MyCompressor }
40
+ ```
41
+
42
+ *Jonathan Hefner*
43
+
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.
50
+
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.
54
+
55
+ The `:serializer` and `:coder` options are mutually exclusive. Specifying
56
+ both will raise an `ArgumentError`.
57
+
58
+ *Jonathan Hefner*
22
59
 
23
60
  * Fix `ActiveSupport::Inflector.humanize(nil)` raising ``NoMethodError: undefined method `end_with?' for nil:NilClass``.
24
61
 
25
62
  *James Robinson*
26
63
 
27
- * Fix `Enumerable#sum` for `Enumerator#lazy`.
64
+ * Don't show secrets for `ActiveSupport::KeyGenerator#inspect`.
65
+
66
+ Before:
67
+
68
+ ```ruby
69
+ ActiveSupport::KeyGenerator.new(secret).inspect
70
+ "#<ActiveSupport::KeyGenerator:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
71
+ ```
72
+
73
+ After:
74
+
75
+ ```ruby
76
+ ActiveSupport::KeyGenerator::Aes256Gcm(secret).inspect
77
+ "#<ActiveSupport::KeyGenerator:0x0000000104888038>"
78
+ ```
28
79
 
29
- *fatkodima*, *Matthew Draper*, *Jonathan Hefner*
80
+ *Petrik de Heus*
30
81
 
31
82
  * Improve error message when EventedFileUpdateChecker is used without a
32
83
  compatible version of the Listen gem
33
84
 
34
85
  *Hartley McGuire*
35
86
 
87
+ * Add `:report` behavior for Deprecation
36
88
 
37
- ## Rails 7.0.6 (June 29, 2023) ##
89
+ Setting `config.active_support.deprecation = :report` uses the error
90
+ reporter to report deprecation warnings to `ActiveSupport::ErrorReporter`.
38
91
 
39
- * Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
40
- methods
92
+ Deprecations are reported as handled errors, with a severity of `:warning`.
41
93
 
42
- *Hartley McGuire*
94
+ Useful to report deprecations happening in production to your bug tracker.
43
95
 
44
- * Fix arguments being destructed `Enumerable#many?` with block.
96
+ *Étienne Barrié*
45
97
 
46
- *Andrew Novoselac*
98
+ * Rename `Range#overlaps?` to `#overlap?` and add alias for backwards compatibility
47
99
 
48
- * Fix humanize for strings ending with id.
100
+ *Christian Schmidt*
49
101
 
50
- *fatkodima*
102
+ * Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
103
+ methods
51
104
 
105
+ *Hartley McGuire*
52
106
 
53
- ## Rails 7.0.5.1 (June 26, 2023) ##
107
+ * Don't show secrets for `MessageEncryptor#inspect`.
54
108
 
55
- * No changes.
109
+ Before:
56
110
 
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
+ ```
57
115
 
58
- ## Rails 7.0.5 (May 24, 2023) ##
116
+ After:
59
117
 
60
- * Fixes TimeWithZone ArgumentError.
118
+ ```ruby
119
+ ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
120
+ "#<ActiveSupport::MessageEncryptor:0x0000000104888038>"
121
+ ```
61
122
 
62
- *Niklas Häusele*
123
+ *Petrik de Heus*
63
124
 
125
+ * Don't show contents for `EncryptedConfiguration#inspect`.
64
126
 
65
- ## Rails 7.0.4.3 (March 13, 2023) ##
127
+ Before:
128
+ ```ruby
129
+ Rails.application.credentials.inspect
130
+ "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8 ... @config={:secret=>\"something secret\"} ... @key_file_contents=\"915e4ea054e011022398dc242\" ...>"
131
+ ```
66
132
 
67
- * Implement SafeBuffer#bytesplice
133
+ After:
134
+ ```ruby
135
+ Rails.application.credentials.inspect
136
+ "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8>"
137
+ ```
68
138
 
69
- [CVE-2023-28120]
139
+ *Petrik de Heus*
70
140
 
141
+ * `ERB::Util.html_escape_once` always returns an `html_safe` string.
71
142
 
72
- ## Rails 7.0.4.2 (January 24, 2023) ##
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.
73
146
 
74
- * No changes.
147
+ As an example, take this view snippet:
75
148
 
149
+ ```html
150
+ <p><%= html_escape_once("this & that &amp; the other") %></p>
151
+ ```
76
152
 
77
- ## Rails 7.0.4.1 (January 17, 2023) ##
153
+ Before this change, that would be double-escaped and render as:
78
154
 
79
- * Avoid regex backtracking in Inflector.underscore
155
+ ```html
156
+ <p>this &amp;amp; that &amp;amp; the other</p>
157
+ ```
80
158
 
81
- [CVE-2023-22796]
159
+ After this change, it renders correctly as:
82
160
 
161
+ ```html
162
+ <p>this &amp; that &amp; the other</p>
163
+ ```
83
164
 
84
- ## Rails 7.0.4 (September 09, 2022) ##
165
+ Fixes #48256
85
166
 
86
- * Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
167
+ *Mike Dalessio*
87
168
 
88
- Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
89
- process closed the read end, wrote to it, and then terminated (which
90
- presumably closed the file descriptors on its end). The parent process
91
- closed the write end, read from it, and returned, never closing the read
92
- end.
169
+ * Deprecate `SafeBuffer#clone_empty`.
93
170
 
94
- This resulted in an accumulation of open file descriptors, which could
95
- cause errors if the limit is reached.
171
+ This method has not been used internally since Rails 4.2.0.
96
172
 
97
- *Sam Bostock*
173
+ *Mike Dalessio*
98
174
 
99
- * Redis cache store is now compatible with redis-rb 5.0.
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).
100
179
 
101
- *Jean Boussier*
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:
102
183
 
103
- * Fix `NoMethodError` on custom `ActiveSupport::Deprecation` behavior.
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)
104
188
 
105
- `ActiveSupport::Deprecation.behavior=` was supposed to accept any object
106
- that responds to `call`, but in fact its internal implementation assumed that
107
- this object could respond to `arity`, so it was restricted to only `Proc` objects.
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]
108
194
 
109
- This change removes this `arity` restriction of custom behaviors.
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
+ ```
110
201
 
111
- *Ryo Nakamura*
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.
112
209
 
210
+ *Jonathan Hefner*
113
211
 
114
- ## Rails 7.0.3.1 (July 12, 2022) ##
212
+ * A new `7.1` cache format is available which includes an optimization for
213
+ bare string values such as view fragments.
115
214
 
116
- * No changes.
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.
117
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.
118
225
 
119
- ## Rails 7.0.3 (May 09, 2022) ##
226
+ *Jonathan Hefner*
120
227
 
121
- * No changes.
228
+ * Active Support cache stores can now use a preconfigured serializer based on
229
+ `ActiveSupport::MessagePack` via the `:serializer` option:
122
230
 
231
+ ```ruby
232
+ config.cache_store = :redis_cache_store, { serializer: :message_pack }
233
+ ```
123
234
 
124
- ## Rails 7.0.2.4 (April 26, 2022) ##
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).
125
238
 
126
- * Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
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.
127
243
 
128
- Add the method `ERB::Util.xml_name_escape` to escape dangerous characters
129
- in names of tags and names of attributes, following the specification of XML.
244
+ *Jonathan Hefner*
130
245
 
131
- *Álvaro Martín Fraguas*
246
+ * `Object#deep_dup` no longer duplicate named classes and modules.
132
247
 
133
- ## Rails 7.0.2.3 (March 08, 2022) ##
248
+ Before:
134
249
 
135
- * No changes.
250
+ ```ruby
251
+ hash = { class: Object, module: Kernel }
252
+ hash.deep_dup # => {:class=>#<Class:0x00000001063ffc80>, :module=>#<Module:0x00000001063ffa00>}
253
+ ```
136
254
 
255
+ After:
137
256
 
138
- ## Rails 7.0.2.2 (February 11, 2022) ##
257
+ ```ruby
258
+ hash = { class: Object, module: Kernel }
259
+ hash.deep_dup # => {:class=>Object, :module=>Kernel}
260
+ ```
139
261
 
140
- * Fix Reloader method signature to work with the new Executor signature
262
+ *Jean Boussier*
141
263
 
264
+ * Consistently raise an `ArgumentError` if the `ActiveSupport::Cache` key is blank.
142
265
 
143
- ## Rails 7.0.2.1 (February 11, 2022) ##
266
+ *Joshua Young*
144
267
 
145
- * No changes.
268
+ * Deprecate usage of the singleton `ActiveSupport::Deprecation`.
146
269
 
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.
147
273
 
148
- ## Rails 7.0.2 (February 08, 2022) ##
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
149
281
 
150
- * Fix `ActiveSupport::EncryptedConfiguration` to be compatible with Psych 4
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).
151
284
 
152
- *Stephen Sugden*
285
+ ```ruby
286
+ Rails.application.deprecators.silence do
287
+ # code that emits deprecation warnings
288
+ end
289
+ ```
153
290
 
154
- * Improve `File.atomic_write` error handling.
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.
155
295
 
156
- *Daniel Pepper*
296
+ ```ruby
297
+ initializer "my_gem.deprecator" do |app|
298
+ app.deprecators[:my_gem] = MyGem.deprecator
299
+ end
300
+ ```
157
301
 
302
+ *Étienne Barrié*
158
303
 
159
- ## Rails 7.0.1 (January 06, 2022) ##
304
+ * Add `Object#with` to set and restore public attributes around a block
160
305
 
161
- * Fix `Class#descendants` and `DescendantsTracker#descendants` compatibility with Ruby 3.1.
162
-
163
- [The native `Class#descendants` was reverted prior to Ruby 3.1 release](https://bugs.ruby-lang.org/issues/14394#note-33),
164
- but `Class#subclasses` was kept, breaking the feature detection.
306
+ ```ruby
307
+ client.timeout # => 5
308
+ client.with(timeout: 1) do
309
+ client.timeout # => 1
310
+ end
311
+ client.timeout # => 5
312
+ ```
165
313
 
166
314
  *Jean Boussier*
167
315
 
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`.
318
+
319
+ *Rafael Mendonça França*
320
+
321
+ * Deprecate `config.active_support.use_rfc4122_namespaced_uuids`.
168
322
 
169
- ## Rails 7.0.0 (December 15, 2021) ##
323
+ *Rafael Mendonça França*
170
324
 
171
- * Fix `ActiveSupport::Duration.build` to support negative values.
325
+ * Remove implicit conversion of objects into `String` by `ActiveSupport::SafeBuffer`.
172
326
 
173
- The algorithm to collect the `parts` of the `ActiveSupport::Duration`
174
- ignored the sign of the `value` and accumulated incorrect part values. This
175
- impacted `ActiveSupport::Duration#sum` (which is dependent on `parts`) but
176
- not `ActiveSupport::Duration#eql?` (which is dependent on `value`).
327
+ *Rafael Mendonça França*
177
328
 
178
- *Caleb Buxton*, *Braden Staudacher*
329
+ * Remove deprecated `active_support/core_ext/range/include_time_with_zone` file.
179
330
 
331
+ *Rafael Mendonça França*
180
332
 
181
- ## Rails 7.0.0.rc3 (December 14, 2021) ##
333
+ * Deprecate `config.active_support.remove_deprecated_time_with_zone_name`.
182
334
 
183
- * No changes.
335
+ *Rafael Mendonça França*
184
336
 
337
+ * Remove deprecated override of `ActiveSupport::TimeWithZone.name`.
185
338
 
186
- ## Rails 7.0.0.rc2 (December 14, 2021) ##
339
+ *Rafael Mendonça França*
187
340
 
188
- * No changes.
341
+ * Deprecate `config.active_support.disable_to_s_conversion`.
189
342
 
190
- ## Rails 7.0.0.rc1 (December 06, 2021) ##
343
+ *Rafael Mendonça França*
191
344
 
192
- * Deprecate passing a format to `#to_s` in favor of `#to_formatted_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
345
+ * Remove deprecated option to passing a format to `#to_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
193
346
  `BigDecimal`, `Float` and, `Integer`.
194
347
 
195
348
  *Rafael Mendonça França*
196
349
 
197
- * Document `ActiveSupport::Testing::Deprecation`.
350
+ * Remove deprecated `ActiveSupport::PerThreadRegistry`.
198
351
 
199
- *Sam Bostock & Sam Jordan*
352
+ *Rafael Mendonça França*
200
353
 
201
- * Add `Pathname#existence`.
354
+ * Remove deprecated override of `Enumerable#sum`.
202
355
 
203
- ```ruby
204
- Pathname.new("file").existence&.read
205
- ```
356
+ *Rafael Mendonça França*
206
357
 
207
- *Timo Schilling*
358
+ * Deprecated initializing a `ActiveSupport::Cache::MemCacheStore` with an instance of `Dalli::Client`.
208
359
 
209
- * Remove deprecate `ActiveSupport::Multibyte::Unicode.default_normalization_form`.
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.
210
361
 
211
- *Rafael Mendonça França*
362
+ *aledustet*
212
363
 
213
- * Remove deprecated support to use `Range#include?` to check the inclusion of a value in
214
- a date time range is deprecated.
364
+ * Stub `Time.new()` in `TimeHelpers#travel_to`
215
365
 
216
- *Rafael Mendonça França*
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
+ ```
217
372
 
218
- * Remove deprecated `URI.parser`.
373
+ *fatkodima*
219
374
 
220
- *Rafael Mendonça França*
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:
221
381
 
222
- * Remove deprecated `config.active_support.use_sha1_digests`.
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
223
387
 
224
- *Rafael Mendonça França*
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
+ ```
225
396
 
226
- * Invoking `Object#with_options` without a `&block` argument returns the
227
- `ActiveSupport::OptionMerger` instance.
397
+ *Jonathan Hefner*
228
398
 
229
- *Sean Doyle*
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:
230
403
 
231
- * `Rails.application.executor` hooks can now be called around every test
404
+ ```ruby
405
+ encryptor = ActiveSupport::MessageEncryptor.new(secret)
406
+ message = encryptor.encrypt_and_sign(nil)
232
407
 
233
- This helps to better simulate request or job local state being reset around tests and prevents state
234
- leaking from one test to another.
408
+ encryptor.decrypt_and_verify(message)
409
+ # => nil
235
410
 
236
- However it requires the executor hooks executed in the test environment to be re-entrant.
411
+ verifier = ActiveSupport::MessageVerifier.new(secret)
412
+ message = verifier.generate(nil)
237
413
 
238
- To enable this, set `config.active_support.executor_around_test_case = true` (this is the default in Rails 7).
414
+ verifier.verified(message)
415
+ # => nil
239
416
 
240
- *Jean Boussier*
417
+ verifier.verify(message)
418
+ # BEFORE:
419
+ # => raises ActiveSupport::MessageVerifier::InvalidSignature
420
+ # AFTER:
421
+ # => nil
422
+ ```
241
423
 
242
- * `ActiveSupport::DescendantsTracker` now mostly delegate to `Class#descendants` on Ruby 3.1
424
+ *Jonathan Hefner*
243
425
 
244
- Ruby now provides a fast `Class#descendants` making `ActiveSupport::DescendantsTracker` mostly useless.
426
+ * Maintain `html_safe?` on html_safe strings when sliced with `slice`, `slice!`, or `chr` method.
245
427
 
246
- As a result the following methods are deprecated:
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.
247
430
 
248
- - `ActiveSupport::DescendantsTracker.direct_descendants`
249
- - `ActiveSupport::DescendantsTracker#direct_descendants`
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
+ ```
250
439
 
251
- *Jean Boussier*
440
+ *Michael Go*
252
441
 
253
- * Fix the `Digest::UUID.uuid_from_hash` behavior for namespace IDs that are different from the ones defined on `Digest::UUID`.
442
+ * Add `Object#in?` support for open ranges.
254
443
 
255
- The new behavior will be enabled by setting the
256
- `config.active_support.use_rfc4122_namespaced_uuids` option to `true`
257
- and is the default for new apps.
444
+ ```ruby
445
+ assert Date.today.in?(..Date.tomorrow)
446
+ assert_not Date.today.in?(Date.tomorrow..)
447
+ ```
258
448
 
259
- The old behavior is the default for upgraded apps and will output a
260
- deprecation warning every time a value that is different than one of
261
- the constants defined on the `Digest::UUID` extension is used as the
262
- namespace ID.
449
+ *Ignacio Galindo*
263
450
 
264
- *Alex Robbin*, *Erich Soares Machado*, *Eugene Kenny*
451
+ * `config.i18n.raise_on_missing_translations = true` now raises on any missing translation.
265
452
 
266
- * `ActiveSupport::Inflector::Inflections#clear(:acronyms)` is now supported,
267
- and `inflector.clear` / `inflector.clear(:all)` also clears acronyms.
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.
268
455
 
269
- *Alex Ghiculescu*, *Oliver Peate*
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.
270
458
 
459
+ *Alex Ghiculescu*
271
460
 
272
- ## Rails 7.0.0.alpha2 (September 15, 2021) ##
461
+ * `ActiveSupport::CurrentAttributes` now raises if a restricted attribute name is used.
273
462
 
274
- * No changes.
463
+ Attributes such as `set` and `reset` cannot be used as they clash with the
464
+ `CurrentAttributes` public API.
275
465
 
466
+ *Alex Ghiculescu*
276
467
 
277
- ## Rails 7.0.0.alpha1 (September 15, 2021) ##
468
+ * `HashWithIndifferentAccess#transform_keys` now takes a Hash argument, just
469
+ as Ruby's `Hash#transform_keys` does.
278
470
 
279
- * `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.
471
+ *Akira Matsuda*
280
472
 
281
- *Xavier Noria*
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.
282
477
 
283
- * Private internal classes of `ActiveSupport::Dependencies` have been deleted, like `ActiveSupport::Dependencies::Reference`, `ActiveSupport::Dependencies::Blamable`, and others.
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
284
484
 
285
- *Xavier Noria*
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
+ ```
286
492
 
287
- * The private API of `ActiveSupport::Dependencies` has been deleted. That includes methods like `hook!`, `unhook!`, `depend_on`, `require_or_load`, `mechanism`, and many others.
493
+ *Akira Matsuda*
288
494
 
289
- *Xavier Noria*
495
+ * `assert_difference` message now includes what changed.
290
496
 
291
- * Improves the performance of `ActiveSupport::NumberHelper` formatters by avoiding the use of exceptions as flow control.
497
+ This makes it easier to debug non-obvious failures.
292
498
 
293
- *Mike Dalessio*
499
+ Before:
294
500
 
295
- * Removed rescue block from `ActiveSupport::Cache::RedisCacheStore#handle_exception`
501
+ ```
502
+ "User.count" didn't change by 32.
503
+ Expected: 1611
504
+ Actual: 1579
505
+ ```
296
506
 
297
- Previously, if you provided a `error_handler` to `redis_cache_store`, any errors thrown by
298
- the error handler would be rescued and logged only. Removed the `rescue` clause from `handle_exception`
299
- to allow these to be thrown.
507
+ After:
300
508
 
301
- *Nicholas A. Stuart*
509
+ ```
510
+ "User.count" didn't change by 32, but by 0.
511
+ Expected: 1611
512
+ Actual: 1579
513
+ ```
302
514
 
303
- * Allow entirely opting out of deprecation warnings.
515
+ *Alex Ghiculescu*
304
516
 
305
- Previously if you did `app.config.active_support.deprecation = :silence`, some work would
306
- still be done on each call to `ActiveSupport::Deprecation.warn`. In very hot paths, this could
307
- cause performance issues.
517
+ * Add ability to match exception messages to `assert_raises` assertion
308
518
 
309
- Now, you can make `ActiveSupport::Deprecation.warn` a no-op:
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
+ ```
310
526
 
527
+ you can now write this
311
528
  ```ruby
312
- config.active_support.report_deprecations = false
529
+ assert_raises(ArgumentError, match: /incorrect param/i) do
530
+ perform_service(param: 'exception')
531
+ end
313
532
  ```
314
533
 
315
- This is the default in production for new apps. It is the equivalent to:
534
+ *fatkodima*
535
+
536
+ * Add `Rails.env.local?` shorthand for `Rails.env.development? || Rails.env.test?`.
537
+
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)`.
543
+
544
+ *KevSlashNull*, and *serprex*
545
+
546
+ * `ActiveSupport::CurrentAttributes.resets` now accepts a method name
547
+
548
+ The block API is still the recommended approach, but now both APIs are supported:
316
549
 
317
550
  ```ruby
318
- config.active_support.deprecation = :silence
319
- config.active_support.disallowed_deprecation = :silence
551
+ class Current < ActiveSupport::CurrentAttributes
552
+ resets { Time.zone = nil }
553
+ resets :clear_time_zone
554
+ end
320
555
  ```
321
556
 
322
- but will take a more optimised code path.
323
-
324
557
  *Alex Ghiculescu*
325
558
 
326
- * Faster tests by parallelizing only when overhead is justified by the number
327
- of them.
559
+ * Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
560
+
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.
566
+
567
+ This resulted in an accumulation of open file descriptors, which could
568
+ cause errors if the limit is reached.
569
+
570
+ *Sam Bostock*
328
571
 
329
- Running tests in parallel adds overhead in terms of database
330
- setup and fixture loading. Now, Rails will only parallelize test executions when
331
- there are enough tests to make it worth it.
572
+ * Fix `Time#change` and `Time#advance` for times around the end of Daylight
573
+ Saving Time.
332
574
 
333
- This threshold is 50 by default, and is configurable via config setting in
334
- your test.rb:
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:
335
578
 
336
579
  ```ruby
337
- config.active_support.test_parallelization_threshold = 100
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
338
596
  ```
339
597
 
340
- It's also configurable at the test case level:
598
+ And the DST offset would always be chosen for times with a `TimeZone`
599
+ object:
341
600
 
342
601
  ```ruby
343
- class ActiveSupport::TestCase
344
- parallelize threshold: 100
345
- end
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
+ ```
618
+
619
+ Now, `Time#change` and `Time#advance` will choose the offset that matches
620
+ the original time's offset when possible:
621
+
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
346
654
  ```
347
655
 
348
- *Jorge Manrubia*
656
+ *Kevin Hall*, *Takayoshi Nishida*, and *Jonathan Hefner*
349
657
 
350
- * OpenSSL constants are now used for Digest computations.
658
+ * Fix MemoryStore to preserve entries TTL when incrementing or decrementing
351
659
 
352
- *Dirkjan Bussink*
660
+ This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.
661
+
662
+ *Jean Boussier*
353
663
 
354
- * `TimeZone.iso8601` now accepts valid ordinal values similar to Ruby's `Date._iso8601` method.
355
- A valid ordinal value will be converted to an instance of `TimeWithZone` using the `:year`
356
- and `:yday` fragments returned from `Date._iso8601`.
664
+ * `Rails.error.handle` and `Rails.error.record` filter now by multiple error classes.
357
665
 
358
666
  ```ruby
359
- twz = ActiveSupport::TimeZone["Eastern Time (US & Canada)"].iso8601("21087")
360
- twz.to_a[0, 6] == [0, 0, 0, 28, 03, 2021]
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
361
671
  ```
362
672
 
363
- *Steve Laing*
673
+ *Martin Spickermann*
364
674
 
365
- * `Time#change` and methods that call it (e.g. `Time#advance`) will now
366
- return a `Time` with the timezone argument provided, if the caller was
367
- initialized with a timezone argument.
675
+ * `Class#subclasses` and `Class#descendants` now automatically filter reloaded classes.
368
676
 
369
- Fixes [#42467](https://github.com/rails/rails/issues/42467).
677
+ Previously they could return old implementations of reloadable classes that have been
678
+ dereferenced but not yet garbage collected.
370
679
 
371
- *Alex Ghiculescu*
680
+ They now automatically filter such classes like `DescendantTracker#subclasses` and
681
+ `DescendantTracker#descendants`.
372
682
 
373
- * Allow serializing any module or class to JSON by name.
683
+ *Jean Boussier*
374
684
 
375
- *Tyler Rick*, *Zachary Scott*
685
+ * `Rails.error.report` now marks errors as reported to avoid reporting them twice.
376
686
 
377
- * Raise `ActiveSupport::EncryptedFile::MissingKeyError` when the
378
- `RAILS_MASTER_KEY` environment variable is blank (e.g. `""`).
687
+ In some cases, users might want to report errors explicitly with some extra context
688
+ before letting it bubble up.
379
689
 
380
- *Sunny Ripert*
690
+ This also allows to safely catch and report errors outside of the execution context.
381
691
 
382
- * The `from:` option is added to `ActiveSupport::TestCase#assert_no_changes`.
692
+ *Jean Boussier*
383
693
 
384
- It permits asserting on the initial value that is expected not to change.
694
+ * Add `assert_error_reported` and `assert_no_error_reported`
695
+
696
+ Allows to easily asserts an error happened but was handled
385
697
 
386
698
  ```ruby
387
- assert_no_changes -> { Status.all_good? }, from: true do
388
- post :create, params: { status: { ok: true } }
699
+ report = assert_error_reported(IOError) do
700
+ # ...
389
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?
390
706
  ```
391
707
 
392
- *George Claghorn*
708
+ *Jean Boussier*
393
709
 
394
- * Deprecate `ActiveSupport::SafeBuffer`'s incorrect implicit conversion of objects into string.
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.
395
714
 
396
- Except for a few methods like `String#%`, objects must implement `#to_str`
397
- to be implicitly converted to a String in string operations. In some
398
- circumstances `ActiveSupport::SafeBuffer` was incorrectly calling the
399
- explicit conversion method (`#to_s`) on them. This behavior is now
400
- deprecated.
715
+ 3-arity and splat-args callbacks such as the following will now be passed
716
+ the deprecator instance as their third argument:
401
717
 
402
- *Jean Boussier*
718
+ * `->(message, callstack, deprecator) { ... }`
719
+ * `->(*args) { ... }`
720
+ * `->(message, *other_args) { ... }`
403
721
 
404
- * Allow nested access to keys on `Rails.application.credentials`.
722
+ 2-arity and 4-arity callbacks such as the following will continue to behave
723
+ the same as before:
405
724
 
406
- Previously only top level keys in `credentials.yml.enc` could be accessed with method calls. Now any key can.
725
+ * `->(message, callstack) { ... }`
726
+ * `->(message, callstack, deprecation_horizon, gem_name) { ... }`
727
+ * `->(message, callstack, *deprecation_details) { ... }`
407
728
 
408
- For example, given these secrets:
729
+ *Jonathan Hefner*
409
730
 
410
- ```yml
411
- aws:
412
- access_key_id: 123
413
- secret_access_key: 345
731
+ * `ActiveSupport::Deprecation#disallowed_warnings` now affects the instance on
732
+ which it is configured.
733
+
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`.
738
+
739
+ **Before**
740
+
741
+ ```ruby
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"
414
750
  ```
415
751
 
416
- `Rails.application.credentials.aws.access_key_id` will now return the same thing as
417
- `Rails.application.credentials.aws[:access_key_id]`.
752
+ **After**
418
753
 
419
- *Alex Ghiculescu*
754
+ ```ruby
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
763
+ ```
764
+
765
+ Note that global `ActiveSupport::Deprecation` methods such as `ActiveSupport::Deprecation.warn`
766
+ and `ActiveSupport::Deprecation.disallowed_warnings` have been deprecated.
767
+
768
+ *Jonathan Hefner*
769
+
770
+ * Add italic and underline support to `ActiveSupport::LogSubscriber#color`
771
+
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.
775
+
776
+ ```ruby
777
+ info color("Hello world!", :red, bold: true, underline: true)
778
+ ```
779
+
780
+ *Gannon McGibbon*
781
+
782
+ * Add `String#downcase_first` method.
783
+
784
+ This method is the corollary of `String#upcase_first`.
785
+
786
+ *Mark Schneider*
787
+
788
+ * `thread_mattr_accessor` will call `.dup.freeze` on non-frozen default values.
789
+
790
+ This provides a basic level of protection against different threads trying
791
+ to mutate a shared default object.
792
+
793
+ *Jonathan Hefner*
794
+
795
+ * Add `raise_on_invalid_cache_expiration_time` config to `ActiveSupport::Cache::Store`
796
+
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.
799
+
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`.
802
+
803
+ *Trevor Turk*
804
+
805
+ * `ActiveSupport::Cache:Store#fetch` now passes an options accessor to the block.
806
+
807
+ It makes possible to override cache options:
808
+
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
815
+
816
+ *Andrii Gladkyi*, *Jean Boussier*
817
+
818
+ * `default` option of `thread_mattr_accessor` now applies through inheritance and
819
+ also across new threads.
420
820
 
421
- * Added a faster and more compact `ActiveSupport::Cache` serialization format.
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.
422
824
 
423
- It can be enabled with `config.active_support.cache_format_version = 7.0` or
424
- `config.load_defaults 7.0`. Regardless of the configuration Active Support
425
- 7.0 can read cache entries serialized by Active Support 6.1 which allows to
426
- upgrade without invalidating the cache. However Rails 6.1 can't read the
427
- new format, so all readers must be upgraded before the new format is enabled.
825
+ Fixes #43312.
826
+
827
+ *Thierry Deo*
828
+
829
+ * Redis cache store is now compatible with redis-rb 5.0.
428
830
 
429
831
  *Jean Boussier*
430
832
 
431
- * Add `Enumerable#sole`, per `ActiveRecord::FinderMethods#sole`. Returns the
432
- sole item of the enumerable, raising if no items are found, or if more than
433
- one is.
833
+ * Add `skip_nil:` support to `ActiveSupport::Cache::Store#fetch_multi`.
434
834
 
435
- *Asherah Connor*
835
+ *Daniel Alfaro*
436
836
 
437
- * Freeze `ActiveSupport::Duration#parts` and remove writer methods.
837
+ * Add `quarter` method to date/time
438
838
 
439
- Durations are meant to be value objects and should not be mutated.
839
+ *Matt Swanson*
440
840
 
441
- *Andrew White*
841
+ * Fix `NoMethodError` on custom `ActiveSupport::Deprecation` behavior.
442
842
 
443
- * Fix `ActiveSupport::TimeZone#utc_to_local` with fractional seconds.
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.
444
846
 
445
- When `utc_to_local_returns_utc_offset_times` is false and the time
446
- instance had fractional seconds the new UTC time instance was out by
447
- a factor of 1,000,000 as the `Time.utc` constructor takes a usec
448
- value and not a fractional second value.
847
+ This change removes this `arity` restriction of custom behaviors.
449
848
 
450
- *Andrew White*
849
+ *Ryo Nakamura*
850
+
851
+ * Support `:url_safe` option for `MessageEncryptor`.
852
+
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.
856
+
857
+ *Jonathan Hefner*
858
+
859
+ * Add `url_safe` option to `ActiveSupport::MessageVerifier` initializer
451
860
 
452
- * Add `expires_at` argument to `ActiveSupport::Cache` `write` and `fetch` to set a cache entry TTL as an absolute time.
861
+ `ActiveSupport::MessageVerifier.new` now takes optional `url_safe` argument.
862
+ It can generate URL-safe strings by passing `url_safe: true`.
453
863
 
454
864
  ```ruby
455
- Rails.cache.write(key, value, expires_at: Time.now.at_end_of_hour)
865
+ verifier = ActiveSupport::MessageVerifier.new(url_safe: true)
866
+ message = verifier.generate(data) # => URL-safe string
456
867
  ```
457
868
 
458
- *Jean Boussier*
869
+ This option is `false` by default to be backwards compatible.
459
870
 
460
- * Deprecate `ActiveSupport::TimeWithZone.name` so that from Rails 7.1 it will use the default implementation.
871
+ *Shouichi Kamiya*
461
872
 
462
- *Andrew White*
873
+ * Enable connection pooling by default for `MemCacheStore` and `RedisCacheStore`.
874
+
875
+ If you want to disable connection pooling, set `:pool` option to `false` when configuring the cache store:
876
+
877
+ ```ruby
878
+ config.cache_store = :mem_cache_store, "cache.example.com", pool: false
879
+ ```
463
880
 
464
- * Deprecates Rails custom `Enumerable#sum` and `Array#sum` in favor of Ruby's native implementation which
465
- is considerably faster.
881
+ *fatkodima*
466
882
 
467
- Ruby requires an initializer for non-numeric type as per examples below:
883
+ * Add `force:` support to `ActiveSupport::Cache::Store#fetch_multi`.
884
+
885
+ *fatkodima*
886
+
887
+ * Deprecated `:pool_size` and `:pool_timeout` options for configuring connection pooling in cache stores.
888
+
889
+ Use `pool: true` to enable pooling with default settings:
468
890
 
469
891
  ```ruby
470
- %w[foo bar].sum('')
471
- # instead of %w[foo bar].sum
892
+ config.cache_store = :redis_cache_store, pool: true
893
+ ```
472
894
 
473
- [[1, 2], [3, 4, 5]].sum([])
474
- # 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 }
475
899
  ```
476
900
 
477
- *Alberto Mota*
901
+ *fatkodima*
902
+
903
+ * Allow #increment and #decrement methods of `ActiveSupport::Cache::Store`
904
+ subclasses to set new values.
478
905
 
479
- * 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.
480
908
 
481
- 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*
482
910
 
483
- *Ricardo Díaz*
911
+ * Add `skip_nil:` support to `RedisCacheStore`
484
912
 
485
- * Fix proxying keyword arguments in `ActiveSupport::CurrentAttributes`.
913
+ *Joey Paris*
486
914
 
487
- *Marcin Kołodziej*
915
+ * `ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true)` now
916
+ correctly writes expired keys.
488
917
 
489
- * Add `Enumerable#maximum` and `Enumerable#minimum` to easily calculate the maximum or minimum from extracted
490
- elements of an enumerable.
918
+ *Alan Savage*
491
919
 
492
- ```ruby
493
- payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
920
+ * `ActiveSupport::ErrorReporter` now accepts and forward a `source:` parameter.
494
921
 
495
- payments.minimum(:price) # => 5
496
- payments.maximum(:price) # => 15
497
- ```
922
+ This allow libraries to signal the origin of the errors, and reporters
923
+ to easily ignore some sources.
498
924
 
499
- This also allows passing enumerables to `fresh_when` and `stale?` in Action Controller.
500
- See PR [#41404](https://github.com/rails/rails/pull/41404) for an example.
925
+ *Jean Boussier*
501
926
 
502
- *Ayrton De Craene*
927
+ * Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
503
928
 
504
- * `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.
505
931
 
506
- ```ruby
507
- config.cache_store = :mem_cache_store, nil
932
+ *Álvaro Martín Fraguas*
508
933
 
509
- # is now equivalent to
934
+ * Respect `ActiveSupport::Logger.new`'s `:formatter` keyword argument
510
935
 
511
- 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`.
512
940
 
513
- # and is also equivalent to
941
+ *Steven Harman*
514
942
 
515
- config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"
943
+ * Deprecate preserving the pre-Ruby 2.4 behavior of `to_time`
516
944
 
517
- # which is the fallback behavior of Dalli
518
- ```
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.
519
951
 
520
- 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.
521
955
 
522
- *Michael Overmeyer*
956
+ *Andrew White*
523
957
 
524
- * 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("")`
525
959
 
526
- *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.
527
962
 
528
- * `ActiveSupport::Inflector.camelize` behaves expected when provided a symbol `:upper` or `:lower` argument. Matches
529
- `String#camelize` behavior.
963
+ That behavior was unlikely to be expected.
530
964
 
531
- *Alex Ghiculescu*
965
+ *Jean Boussier*
966
+
967
+ * Deprecate `Notification::Event`'s `#children` and `#parent_of?`
532
968
 
533
- * Raises an `ArgumentError` when the first argument of `ActiveSupport::Notification.subscribe` is
534
- invalid.
969
+ *John Hawthorn*
535
970
 
536
- *Vipul A M*
971
+ * Change the default serializer of `ActiveSupport::MessageVerifier` from
972
+ `Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
537
973
 
538
- * `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.
539
977
 
540
- *Nathaniel Woodthorpe*
978
+ *Saba Kiaei*, *David Buckley*, and *Jonathan Hefner*
541
979
 
542
- * 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`.
543
982
 
544
- *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.
545
986
 
546
- * Add `RedisCacheStore#stats` method similar to `MemCacheStore#stats`. Calls `redis#info` internally.
987
+ *Zack Deveau*, *Martin Gingras*, and *Jonathan Hefner*
547
988
 
548
- *Ritikesh G*
989
+ * Add `ActiveSupport::TestCase#stub_const` to stub a constant for the duration of a yield.
549
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*
550
1007
 
551
- 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.