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