activesupport 7.0.8 → 7.1.0.beta1

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