activesupport 7.0.8.6 → 7.1.0.beta1

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