activesupport 6.1.0 → 7.1.5.1

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 (225) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1075 -325
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/lib/active_support/actionable_error.rb +4 -2
  6. data/lib/active_support/array_inquirer.rb +2 -2
  7. data/lib/active_support/backtrace_cleaner.rb +32 -7
  8. data/lib/active_support/benchmarkable.rb +3 -2
  9. data/lib/active_support/broadcast_logger.rb +251 -0
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache/coder.rb +153 -0
  12. data/lib/active_support/cache/entry.rb +134 -0
  13. data/lib/active_support/cache/file_store.rb +53 -20
  14. data/lib/active_support/cache/mem_cache_store.rb +201 -62
  15. data/lib/active_support/cache/memory_store.rb +86 -24
  16. data/lib/active_support/cache/null_store.rb +16 -2
  17. data/lib/active_support/cache/redis_cache_store.rb +186 -193
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +63 -71
  20. data/lib/active_support/cache.rb +487 -249
  21. data/lib/active_support/callbacks.rb +227 -105
  22. data/lib/active_support/code_generator.rb +70 -0
  23. data/lib/active_support/concern.rb +9 -7
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/concurrency/share_lock.rb +2 -2
  27. data/lib/active_support/configurable.rb +18 -5
  28. data/lib/active_support/configuration_file.rb +7 -2
  29. data/lib/active_support/core_ext/array/access.rb +1 -5
  30. data/lib/active_support/core_ext/array/conversions.rb +15 -13
  31. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  33. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  34. data/lib/active_support/core_ext/class/subclasses.rb +37 -26
  35. data/lib/active_support/core_ext/date/blank.rb +1 -1
  36. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  37. data/lib/active_support/core_ext/date/conversions.rb +16 -15
  38. data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
  39. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  40. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  41. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  42. data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
  43. data/lib/active_support/core_ext/digest/uuid.rb +30 -13
  44. data/lib/active_support/core_ext/enumerable.rb +85 -83
  45. data/lib/active_support/core_ext/erb/util.rb +196 -0
  46. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  47. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  48. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  49. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  50. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  51. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  52. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  53. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  54. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  55. data/lib/active_support/core_ext/module/attribute_accessors.rb +8 -0
  56. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +49 -22
  57. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  58. data/lib/active_support/core_ext/module/delegation.rb +81 -43
  59. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  60. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  61. data/lib/active_support/core_ext/name_error.rb +2 -8
  62. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  63. data/lib/active_support/core_ext/numeric/conversions.rb +82 -77
  64. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  65. data/lib/active_support/core_ext/object/blank.rb +2 -2
  66. data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
  67. data/lib/active_support/core_ext/object/duplicable.rb +31 -11
  68. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  69. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  70. data/lib/active_support/core_ext/object/json.rb +49 -27
  71. data/lib/active_support/core_ext/object/to_query.rb +2 -4
  72. data/lib/active_support/core_ext/object/try.rb +20 -20
  73. data/lib/active_support/core_ext/object/with.rb +44 -0
  74. data/lib/active_support/core_ext/object/with_options.rb +25 -6
  75. data/lib/active_support/core_ext/object.rb +1 -0
  76. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  77. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  78. data/lib/active_support/core_ext/pathname.rb +4 -0
  79. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  80. data/lib/active_support/core_ext/range/conversions.rb +34 -13
  81. data/lib/active_support/core_ext/range/each.rb +1 -1
  82. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  83. data/lib/active_support/core_ext/range.rb +1 -2
  84. data/lib/active_support/core_ext/securerandom.rb +25 -13
  85. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  86. data/lib/active_support/core_ext/string/filters.rb +21 -15
  87. data/lib/active_support/core_ext/string/indent.rb +1 -1
  88. data/lib/active_support/core_ext/string/inflections.rb +17 -10
  89. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  90. data/lib/active_support/core_ext/string/output_safety.rb +85 -165
  91. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  92. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  93. data/lib/active_support/core_ext/time/calculations.rb +30 -8
  94. data/lib/active_support/core_ext/time/conversions.rb +15 -13
  95. data/lib/active_support/core_ext/time/zones.rb +12 -28
  96. data/lib/active_support/core_ext.rb +2 -1
  97. data/lib/active_support/current_attributes.rb +47 -20
  98. data/lib/active_support/deep_mergeable.rb +53 -0
  99. data/lib/active_support/dependencies/autoload.rb +17 -12
  100. data/lib/active_support/dependencies/interlock.rb +10 -18
  101. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  102. data/lib/active_support/dependencies.rb +58 -788
  103. data/lib/active_support/deprecation/behaviors.rb +66 -40
  104. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  105. data/lib/active_support/deprecation/deprecators.rb +104 -0
  106. data/lib/active_support/deprecation/disallowed.rb +6 -8
  107. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  108. data/lib/active_support/deprecation/method_wrappers.rb +9 -26
  109. data/lib/active_support/deprecation/proxy_wrappers.rb +38 -23
  110. data/lib/active_support/deprecation/reporting.rb +43 -26
  111. data/lib/active_support/deprecation.rb +32 -5
  112. data/lib/active_support/deprecator.rb +7 -0
  113. data/lib/active_support/descendants_tracker.rb +150 -72
  114. data/lib/active_support/digest.rb +5 -3
  115. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  116. data/lib/active_support/duration/iso8601_serializer.rb +9 -3
  117. data/lib/active_support/duration.rb +83 -52
  118. data/lib/active_support/encrypted_configuration.rb +72 -9
  119. data/lib/active_support/encrypted_file.rb +29 -13
  120. data/lib/active_support/environment_inquirer.rb +23 -3
  121. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  122. data/lib/active_support/error_reporter.rb +203 -0
  123. data/lib/active_support/evented_file_update_checker.rb +20 -7
  124. data/lib/active_support/execution_context/test_helper.rb +13 -0
  125. data/lib/active_support/execution_context.rb +53 -0
  126. data/lib/active_support/execution_wrapper.rb +44 -22
  127. data/lib/active_support/executor/test_helper.rb +7 -0
  128. data/lib/active_support/file_update_checker.rb +4 -2
  129. data/lib/active_support/fork_tracker.rb +28 -11
  130. data/lib/active_support/gem_version.rb +4 -4
  131. data/lib/active_support/gzip.rb +2 -0
  132. data/lib/active_support/hash_with_indifferent_access.rb +44 -19
  133. data/lib/active_support/html_safe_translation.rb +53 -0
  134. data/lib/active_support/i18n.rb +2 -1
  135. data/lib/active_support/i18n_railtie.rb +21 -14
  136. data/lib/active_support/inflector/inflections.rb +25 -7
  137. data/lib/active_support/inflector/methods.rb +50 -64
  138. data/lib/active_support/inflector/transliterate.rb +4 -2
  139. data/lib/active_support/isolated_execution_state.rb +76 -0
  140. data/lib/active_support/json/decoding.rb +2 -1
  141. data/lib/active_support/json/encoding.rb +27 -45
  142. data/lib/active_support/key_generator.rb +31 -6
  143. data/lib/active_support/lazy_load_hooks.rb +33 -7
  144. data/lib/active_support/locale/en.yml +4 -2
  145. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  146. data/lib/active_support/log_subscriber.rb +97 -35
  147. data/lib/active_support/logger.rb +9 -60
  148. data/lib/active_support/logger_thread_safe_level.rb +11 -34
  149. data/lib/active_support/message_encryptor.rb +206 -56
  150. data/lib/active_support/message_encryptors.rb +141 -0
  151. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  152. data/lib/active_support/message_pack/extensions.rb +292 -0
  153. data/lib/active_support/message_pack/serializer.rb +63 -0
  154. data/lib/active_support/message_pack.rb +50 -0
  155. data/lib/active_support/message_verifier.rb +235 -84
  156. data/lib/active_support/message_verifiers.rb +135 -0
  157. data/lib/active_support/messages/codec.rb +65 -0
  158. data/lib/active_support/messages/metadata.rb +112 -46
  159. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  160. data/lib/active_support/messages/rotator.rb +34 -32
  161. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  162. data/lib/active_support/multibyte/chars.rb +12 -11
  163. data/lib/active_support/multibyte/unicode.rb +9 -49
  164. data/lib/active_support/multibyte.rb +1 -1
  165. data/lib/active_support/notifications/fanout.rb +304 -114
  166. data/lib/active_support/notifications/instrumenter.rb +117 -35
  167. data/lib/active_support/notifications.rb +25 -25
  168. data/lib/active_support/number_helper/number_converter.rb +14 -7
  169. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  170. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  171. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -4
  172. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  173. data/lib/active_support/number_helper/number_to_rounded_converter.rb +10 -6
  174. data/lib/active_support/number_helper/rounding_helper.rb +2 -6
  175. data/lib/active_support/number_helper.rb +379 -319
  176. data/lib/active_support/option_merger.rb +10 -18
  177. data/lib/active_support/ordered_hash.rb +4 -4
  178. data/lib/active_support/ordered_options.rb +15 -1
  179. data/lib/active_support/parameter_filter.rb +105 -81
  180. data/lib/active_support/proxy_object.rb +2 -0
  181. data/lib/active_support/railtie.rb +83 -21
  182. data/lib/active_support/reloader.rb +13 -5
  183. data/lib/active_support/rescuable.rb +18 -16
  184. data/lib/active_support/ruby_features.rb +7 -0
  185. data/lib/active_support/secure_compare_rotator.rb +18 -11
  186. data/lib/active_support/security_utils.rb +1 -1
  187. data/lib/active_support/string_inquirer.rb +3 -3
  188. data/lib/active_support/subscriber.rb +11 -40
  189. data/lib/active_support/syntax_error_proxy.rb +60 -0
  190. data/lib/active_support/tagged_logging.rb +65 -25
  191. data/lib/active_support/test_case.rb +166 -27
  192. data/lib/active_support/testing/assertions.rb +61 -15
  193. data/lib/active_support/testing/autorun.rb +0 -2
  194. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  195. data/lib/active_support/testing/deprecation.rb +53 -2
  196. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  197. data/lib/active_support/testing/isolation.rb +30 -29
  198. data/lib/active_support/testing/method_call_assertions.rb +24 -11
  199. data/lib/active_support/testing/parallelization/server.rb +4 -0
  200. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  201. data/lib/active_support/testing/parallelization.rb +4 -0
  202. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  203. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  204. data/lib/active_support/testing/stream.rb +4 -6
  205. data/lib/active_support/testing/strict_warnings.rb +39 -0
  206. data/lib/active_support/testing/tagged_logging.rb +1 -1
  207. data/lib/active_support/testing/time_helpers.rb +49 -16
  208. data/lib/active_support/time_with_zone.rb +39 -28
  209. data/lib/active_support/values/time_zone.rb +50 -18
  210. data/lib/active_support/version.rb +1 -1
  211. data/lib/active_support/xml_mini/jdom.rb +4 -11
  212. data/lib/active_support/xml_mini/libxml.rb +5 -5
  213. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  214. data/lib/active_support/xml_mini/nokogiri.rb +5 -5
  215. data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
  216. data/lib/active_support/xml_mini/rexml.rb +2 -2
  217. data/lib/active_support/xml_mini.rb +7 -6
  218. data/lib/active_support.rb +28 -1
  219. metadata +150 -18
  220. data/lib/active_support/core_ext/marshal.rb +0 -26
  221. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
  222. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  223. data/lib/active_support/core_ext/uri.rb +0 -29
  224. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
  225. data/lib/active_support/per_thread_registry.rb +0 -60
data/CHANGELOG.md CHANGED
@@ -1,551 +1,1301 @@
1
- ## Rails 6.1.0 (December 09, 2020) ##
1
+ ## Rails 7.1.5.1 (December 10, 2024) ##
2
2
 
3
- * Ensure `MemoryStore` disables compression by default. Reverts behavior of
4
- `MemoryStore` to its prior rails `5.1` behavior.
3
+ * No changes.
5
4
 
6
- *Max Gurewitz*
7
5
 
8
- * Calling `iso8601` on negative durations retains the negative sign on individual
9
- digits instead of prepending it.
6
+ ## Rails 7.1.5 (October 30, 2024) ##
10
7
 
11
- This change is required so we can interoperate with PostgreSQL, which prefers
12
- negative signs for each component.
8
+ * No changes.
13
9
 
14
- Compatibility with other iso8601 parsers which support leading negatives as well
15
- as negatives per component is still retained.
10
+
11
+ ## Rails 7.1.4.2 (October 23, 2024) ##
12
+
13
+ * No changes.
14
+
15
+
16
+ ## Rails 7.1.4.1 (October 15, 2024) ##
17
+
18
+ * No changes.
19
+
20
+
21
+ ## Rails 7.1.4 (August 22, 2024) ##
22
+
23
+ * Improve compatibility for `ActiveSupport::BroadcastLogger`.
24
+
25
+ *Máximo Mussini*
26
+
27
+ * Pass options along to write_entry in handle_expired_entry method.
28
+
29
+ *Graham Cooper*
30
+
31
+ * Fix Active Support configurations deprecations.
32
+
33
+ *fatkodima*
34
+
35
+ * Fix teardown callbacks.
36
+
37
+ *Tristan Starck*
38
+
39
+ * `BacktraceCleaner` silence core internal methods by default.
40
+
41
+ *Jean Boussier*
42
+
43
+ * Fix `delegate_missing_to allow_nil: true` when called with implict self
44
+
45
+ ```ruby
46
+ class Person
47
+ delegate_missing_to :address, allow_nil: true
48
+
49
+ def address
50
+ nil
51
+ end
52
+
53
+ def berliner?
54
+ city == "Berlin"
55
+ end
56
+ end
57
+
58
+ Person.new.city # => nil
59
+ Person.new.berliner? # undefined local variable or method `city' for an instance of Person (NameError)
60
+ ```
61
+
62
+ *Jean Boussier*
63
+
64
+ * Work around a Ruby bug that can cause a VM crash.
65
+
66
+ This would happen if using `TaggerLogger` with a Proc
67
+ formatter on which you called `object_id`.
68
+
69
+ ```
70
+ [BUG] Object ID seen, but not in mapping table: proc
71
+ ```
72
+
73
+ *Jean Boussier*
74
+
75
+ * Fix `ActiveSupport::Notifications.publish_event` to preserve units.
76
+
77
+ This solves the incorrect reporting of time spent running Active Record
78
+ asynchronous queries (by a factor `1000`).
79
+
80
+ *Jean Boussier*
81
+
82
+
83
+ ## Rails 7.1.3.4 (June 04, 2024) ##
84
+
85
+ * No changes.
86
+
87
+
88
+ ## Rails 7.1.3.3 (May 16, 2024) ##
89
+
90
+ * No changes.
91
+
92
+
93
+ ## Rails 7.1.3.2 (February 21, 2024) ##
94
+
95
+ * No changes.
96
+
97
+
98
+ ## Rails 7.1.3.1 (February 21, 2024) ##
99
+
100
+ * No changes.
101
+
102
+
103
+ ## Rails 7.1.3 (January 16, 2024) ##
104
+
105
+ * Handle nil `backtrace_locations` in `ActiveSupport::SyntaxErrorProxy`.
106
+
107
+ *Eugene Kenny*
108
+
109
+ * Fix `ActiveSupport::JSON.encode` to prevent duplicate keys.
110
+
111
+ If the same key exist in both String and Symbol form it could
112
+ lead to the same key being emitted twice.
113
+
114
+ *Manish Sharma*
115
+
116
+ * Fix `ActiveSupport::Cache::Store#read_multi` when using a cache namespace
117
+ and local cache strategy.
118
+
119
+ *Mark Oleson*
120
+
121
+ * Fix `Time.now/DateTime.now/Date.today` to return results in a system timezone after `#travel_to`.
122
+
123
+ There is a bug in the current implementation of #travel_to:
124
+ it remembers a timezone of its argument, and all stubbed methods start
125
+ returning results in that remembered timezone. However, the expected
126
+ behaviour is to return results in a system timezone.
127
+
128
+ *Aleksei Chernenkov*
129
+
130
+ * Fix `:unless_exist` option for `MemoryStore#write` (et al) when using a
131
+ cache namespace.
132
+
133
+ *S. Brent Faulkner*
134
+
135
+ * Fix ActiveSupport::Deprecation to handle blaming generated code.
136
+
137
+ *Jean Boussier*, *fatkodima*
138
+
139
+
140
+ ## Rails 7.1.2 (November 10, 2023) ##
141
+
142
+ * Fix `:expires_in` option for `RedisCacheStore#write_multi`.
143
+
144
+ *fatkodima*
145
+
146
+ * Fix deserialization of non-string "purpose" field in Message serializer
147
+
148
+ *Jacopo Beschi*
149
+
150
+ * Prevent global cache options being overwritten when setting dynamic options
151
+ inside a `ActiveSupport::Cache::Store#fetch` block.
152
+
153
+ *Yasha Krasnou*
154
+
155
+ * Fix missing `require` resulting in `NoMethodError` when running
156
+ `bin/rails secrets:show` or `bin/rails secrets:edit`.
157
+
158
+ *Stephen Ierodiaconou*
159
+
160
+ * Ensure `{down,up}case_first` returns non-frozen string.
161
+
162
+ *Jonathan Hefner*
163
+
164
+ * Fix `#to_fs(:human_size)` to correctly work with negative numbers.
165
+
166
+ *Earlopain*
167
+
168
+ * Fix `BroadcastLogger#dup` so that it duplicates the logger's `broadcasts`.
169
+
170
+ *Andrew Novoselac*
171
+
172
+ * Fix issue where `bootstrap.rb` overwrites the `level` of a `BroadcastLogger`'s `broadcasts`.
173
+
174
+ *Andrew Novoselac*
175
+
176
+ * Fix `ActiveSupport::Cache` to handle outdated Marshal payload from Rails 6.1 format.
177
+
178
+ Active Support's Cache is supposed to treat a Marshal payload that can no longer be
179
+ deserialized as a cache miss. It fail to do so for compressed payload in the Rails 6.1
180
+ legacy format.
181
+
182
+ *Jean Boussier*
183
+
184
+ * Fix `OrderedOptions#dig` for array indexes.
185
+
186
+ *fatkodima*
187
+
188
+ * Fix time travel helpers to work when nested using with separate classes.
189
+
190
+ *fatkodima*
191
+
192
+ * Fix `delete_matched` for file cache store to work with keys longer than the
193
+ max filename size.
194
+
195
+ *fatkodima* and *Jonathan Hefner*
196
+
197
+ * Fix compatibility with the `semantic_logger` gem.
198
+
199
+ The `semantic_logger` gem doesn't behave exactly like stdlib logger in that
200
+ `SemanticLogger#level` returns a Symbol while stdlib `Logger#level` returns an Integer.
201
+
202
+ This caused the various `LogSubscriber` classes in Rails to break when assigned a
203
+ `SemanticLogger` instance.
204
+
205
+ *Jean Boussier*, *ojab*
206
+
207
+ ## Rails 7.1.1 (October 11, 2023) ##
208
+
209
+ * Add support for keyword arguments when delegating calls to custom loggers from `ActiveSupport::BroadcastLogger`.
210
+
211
+ *Edouard Chin*
212
+
213
+ * `NumberHelper`: handle objects responding `to_d`.
214
+
215
+ *fatkodima*
216
+
217
+ * Fix RedisCacheStore to properly set the TTL when incrementing or decrementing.
218
+
219
+ This bug was only impacting Redis server older than 7.0.
220
+
221
+ *Thomas Countz*
222
+
223
+ * Fix MemoryStore to prevent race conditions when incrementing or decrementing.
224
+
225
+ *Pierre Jambet*
226
+
227
+
228
+ ## Rails 7.1.0 (October 05, 2023) ##
229
+
230
+ * No changes.
231
+
232
+
233
+ ## Rails 7.1.0.rc2 (October 01, 2023) ##
234
+
235
+ * Fix `AS::MessagePack` with `ENV["RAILS_MAX_THREADS"]`.
236
+
237
+ *Jonathan Hefner*
238
+
239
+
240
+ ## Rails 7.1.0.rc1 (September 27, 2023) ##
241
+
242
+ * Add a new public API for broadcasting logs
243
+
244
+ This feature existed for a while but was until now a private API.
245
+ Broadcasting log allows to send log message to difference sinks (STDOUT, a file ...) and
246
+ is used by default in the development environment to write logs both on STDOUT and in the
247
+ "development.log" file.
248
+
249
+ Basic usage:
250
+
251
+ ```ruby
252
+ stdout_logger = Logger.new(STDOUT)
253
+ file_logger = Logger.new("development.log")
254
+ broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger, file_logger)
255
+
256
+ broadcast.info("Hello!") # The "Hello!" message is written on STDOUT and in the log file.
257
+ ```
258
+
259
+ Adding other sink(s) to the broadcast:
260
+
261
+ ```ruby
262
+ broadcast = ActiveSupport::BroadcastLogger.new
263
+ broadcast.broadcast_to(Logger.new(STDERR))
264
+ ```
265
+
266
+ Remove a sink from the broadcast:
267
+
268
+ ```ruby
269
+ stdout_logger = Logger.new(STDOUT)
270
+ broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger)
271
+
272
+ broadcast.stop_broadcasting_to(stdout_logger)
273
+ ```
274
+
275
+ *Edouard Chin*
276
+
277
+ * Fix Range#overlap? not taking empty ranges into account on Ruby < 3.3
278
+
279
+ *Nobuyoshi Nakada*, *Shouichi Kamiya*, *Hartley McGuire*
280
+
281
+ * Use Ruby 3.3 Range#overlap? if available
282
+
283
+ *Yasuo Honda*
284
+
285
+
286
+ ## Rails 7.1.0.beta1 (September 13, 2023) ##
287
+
288
+ * Add `bigdecimal` as Active Support dependency that is a bundled gem candidate for Ruby 3.4.
289
+
290
+ `bigdecimal` 3.1.4 or higher version will be installed.
291
+ Ruby 2.7 and 3.0 users who want `bigdecimal` version 2.0.0 or 3.0.0 behavior as a default gem,
292
+ pin the `bigdecimal` version in your application Gemfile.
293
+
294
+ *Koichi ITO*
295
+
296
+ * Add `drb`, `mutex_m` and `base64` that are bundled gem candidates for Ruby 3.4
297
+
298
+ *Yasuo Honda*
299
+
300
+ * When using cache format version >= 7.1 or a custom serializer, expired and
301
+ version-mismatched cache entries can now be detected without deserializing
302
+ their values.
303
+
304
+ *Jonathan Hefner*
305
+
306
+ * Make all cache stores return a boolean for `#delete`
307
+
308
+ Previously the `RedisCacheStore#delete` would return `1` if the entry
309
+ exists and `0` otherwise. Now it returns true if the entry exists and false
310
+ otherwise, just like the other stores.
311
+
312
+ The `FileStore` would return `nil` if the entry doesn't exists and returns
313
+ `false` now as well.
314
+
315
+ *Petrik de Heus*
316
+
317
+ * Active Support cache stores now support replacing the default compressor via
318
+ a `:compressor` option. The specified compressor must respond to `deflate`
319
+ and `inflate`. For example:
320
+
321
+ ```ruby
322
+ module MyCompressor
323
+ def self.deflate(string)
324
+ # compression logic...
325
+ end
326
+
327
+ def self.inflate(compressed)
328
+ # decompression logic...
329
+ end
330
+ end
331
+
332
+ config.cache_store = :redis_cache_store, { compressor: MyCompressor }
333
+ ```
334
+
335
+ *Jonathan Hefner*
336
+
337
+ * Active Support cache stores now support a `:serializer` option. Similar to
338
+ the `:coder` option, serializers must respond to `dump` and `load`. However,
339
+ serializers are only responsible for serializing a cached value, whereas
340
+ coders are responsible for serializing the entire `ActiveSupport::Cache::Entry`
341
+ instance. Additionally, the output from serializers can be automatically
342
+ compressed, whereas coders are responsible for their own compression.
343
+
344
+ Specifying a serializer instead of a coder also enables performance
345
+ optimizations, including the bare string optimization introduced by cache
346
+ format version 7.1.
347
+
348
+ The `:serializer` and `:coder` options are mutually exclusive. Specifying
349
+ both will raise an `ArgumentError`.
350
+
351
+ *Jonathan Hefner*
352
+
353
+ * Fix `ActiveSupport::Inflector.humanize(nil)` raising ``NoMethodError: undefined method `end_with?' for nil:NilClass``.
354
+
355
+ *James Robinson*
356
+
357
+ * Don't show secrets for `ActiveSupport::KeyGenerator#inspect`.
16
358
 
17
359
  Before:
18
360
 
19
- (-1.year - 1.day).iso8601
20
- # => "-P1Y1D"
361
+ ```ruby
362
+ ActiveSupport::KeyGenerator.new(secret).inspect
363
+ "#<ActiveSupport::KeyGenerator:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
364
+ ```
21
365
 
22
366
  After:
23
367
 
24
- (-1.year - 1.day).iso8601
25
- # => "P-1Y-1D"
368
+ ```ruby
369
+ ActiveSupport::KeyGenerator::Aes256Gcm(secret).inspect
370
+ "#<ActiveSupport::KeyGenerator:0x0000000104888038>"
371
+ ```
26
372
 
27
- *Vipul A M*
373
+ *Petrik de Heus*
28
374
 
29
- * Remove deprecated `ActiveSupport::Notifications::Instrumenter#end=`.
375
+ * Improve error message when EventedFileUpdateChecker is used without a
376
+ compatible version of the Listen gem
30
377
 
31
- *Rafael Mendonça França*
378
+ *Hartley McGuire*
32
379
 
33
- * Deprecate `ActiveSupport::Multibyte::Unicode.default_normalization_form`.
380
+ * Add `:report` behavior for Deprecation
34
381
 
35
- *Rafael Mendonça França*
382
+ Setting `config.active_support.deprecation = :report` uses the error
383
+ reporter to report deprecation warnings to `ActiveSupport::ErrorReporter`.
36
384
 
37
- * Remove deprecated `ActiveSupport::Multibyte::Unicode.pack_graphemes`,
38
- `ActiveSupport::Multibyte::Unicode.unpack_graphemes`,
39
- `ActiveSupport::Multibyte::Unicode.normalize`,
40
- `ActiveSupport::Multibyte::Unicode.downcase`,
41
- `ActiveSupport::Multibyte::Unicode.upcase` and `ActiveSupport::Multibyte::Unicode.swapcase`.
385
+ Deprecations are reported as handled errors, with a severity of `:warning`.
42
386
 
43
- *Rafael Mendonça França*
387
+ Useful to report deprecations happening in production to your bug tracker.
44
388
 
45
- * Remove deprecated `ActiveSupport::Multibyte::Chars#consumes?` and `ActiveSupport::Multibyte::Chars#normalize`.
389
+ *Étienne Barrié*
46
390
 
47
- *Rafael Mendonça França*
391
+ * Rename `Range#overlaps?` to `#overlap?` and add alias for backwards compatibility
48
392
 
49
- * Remove deprecated file `active_support/core_ext/range/include_range`.
393
+ *Christian Schmidt*
394
+
395
+ * Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
396
+ methods
397
+
398
+ *Hartley McGuire*
399
+
400
+ * Don't show secrets for `MessageEncryptor#inspect`.
401
+
402
+ Before:
403
+
404
+ ```ruby
405
+ ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
406
+ "#<ActiveSupport::MessageEncryptor:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
407
+ ```
408
+
409
+ After:
410
+
411
+ ```ruby
412
+ ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
413
+ "#<ActiveSupport::MessageEncryptor:0x0000000104888038>"
414
+ ```
415
+
416
+ *Petrik de Heus*
417
+
418
+ * Don't show contents for `EncryptedConfiguration#inspect`.
419
+
420
+ Before:
421
+ ```ruby
422
+ Rails.application.credentials.inspect
423
+ "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8 ... @config={:secret=>\"something secret\"} ... @key_file_contents=\"915e4ea054e011022398dc242\" ...>"
424
+ ```
425
+
426
+ After:
427
+ ```ruby
428
+ Rails.application.credentials.inspect
429
+ "#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8>"
430
+ ```
431
+
432
+ *Petrik de Heus*
433
+
434
+ * `ERB::Util.html_escape_once` always returns an `html_safe` string.
435
+
436
+ This method previously maintained the `html_safe?` property of a string on the return
437
+ value. Because this string has been escaped, however, not marking it as `html_safe` causes
438
+ entities to be double-escaped.
439
+
440
+ As an example, take this view snippet:
441
+
442
+ ```html
443
+ <p><%= html_escape_once("this & that &amp; the other") %></p>
444
+ ```
445
+
446
+ Before this change, that would be double-escaped and render as:
447
+
448
+ ```html
449
+ <p>this &amp;amp; that &amp;amp; the other</p>
450
+ ```
451
+
452
+ After this change, it renders correctly as:
453
+
454
+ ```html
455
+ <p>this &amp; that &amp; the other</p>
456
+ ```
457
+
458
+ Fixes #48256
459
+
460
+ *Mike Dalessio*
461
+
462
+ * Deprecate `SafeBuffer#clone_empty`.
463
+
464
+ This method has not been used internally since Rails 4.2.0.
465
+
466
+ *Mike Dalessio*
467
+
468
+ * `MessageEncryptor`, `MessageVerifier`, and `config.active_support.message_serializer`
469
+ now accept `:message_pack` and `:message_pack_allow_marshal` as serializers.
470
+ These serializers require the [`msgpack` gem](https://rubygems.org/gems/msgpack)
471
+ (>= 1.7.0).
472
+
473
+ The Message Pack format can provide improved performance and smaller payload
474
+ sizes. It also supports round-tripping some Ruby types that are not supported
475
+ by JSON. For example:
476
+
477
+ ```ruby
478
+ verifier = ActiveSupport::MessageVerifier.new("secret")
479
+ data = [{ a: 1 }, { b: 2 }.with_indifferent_access, 1.to_d, Time.at(0, 123)]
480
+ message = verifier.generate(data)
481
+
482
+ # BEFORE with config.active_support.message_serializer = :json
483
+ verifier.verified(message)
484
+ # => [{"a"=>1}, {"b"=>2}, "1.0", "1969-12-31T18:00:00.000-06:00"]
485
+ verifier.verified(message).map(&:class)
486
+ # => [Hash, Hash, String, String]
487
+
488
+ # AFTER with config.active_support.message_serializer = :message_pack
489
+ verifier.verified(message)
490
+ # => [{:a=>1}, {"b"=>2}, 0.1e1, 1969-12-31 18:00:00.000123 -0600]
491
+ verifier.verified(message).map(&:class)
492
+ # => [Hash, ActiveSupport::HashWithIndifferentAccess, BigDecimal, Time]
493
+ ```
494
+
495
+ The `:message_pack` serializer can fall back to deserializing with
496
+ `ActiveSupport::JSON` when necessary, and the `:message_pack_allow_marshal`
497
+ serializer can fall back to deserializing with `Marshal` as well as
498
+ `ActiveSupport::JSON`. Additionally, the `:marshal`, `:json`, and
499
+ `:json_allow_marshal` serializers can now fall back to deserializing with
500
+ `ActiveSupport::MessagePack` when necessary. These behaviors ensure old
501
+ messages can still be read so that migration is easier.
502
+
503
+ *Jonathan Hefner*
504
+
505
+ * A new `7.1` cache format is available which includes an optimization for
506
+ bare string values such as view fragments.
507
+
508
+ The `7.1` cache format is used by default for new apps, and existing apps
509
+ can enable the format by setting `config.load_defaults 7.1` or by setting
510
+ `config.active_support.cache_format_version = 7.1` in `config/application.rb`
511
+ or a `config/environments/*.rb` file.
512
+
513
+ Cache entries written using the `6.1` or `7.0` cache formats can be read
514
+ when using the `7.1` format. To perform a rolling deploy of a Rails 7.1
515
+ upgrade, wherein servers that have not yet been upgraded must be able to
516
+ read caches from upgraded servers, leave the cache format unchanged on the
517
+ first deploy, then enable the `7.1` cache format on a subsequent deploy.
518
+
519
+ *Jonathan Hefner*
520
+
521
+ * Active Support cache stores can now use a preconfigured serializer based on
522
+ `ActiveSupport::MessagePack` via the `:serializer` option:
523
+
524
+ ```ruby
525
+ config.cache_store = :redis_cache_store, { serializer: :message_pack }
526
+ ```
527
+
528
+ The `:message_pack` serializer can reduce cache entry sizes and improve
529
+ performance, but requires the [`msgpack` gem](https://rubygems.org/gems/msgpack)
530
+ (>= 1.7.0).
531
+
532
+ The `:message_pack` serializer can read cache entries written by the default
533
+ serializer, and the default serializer can now read entries written by the
534
+ `:message_pack` serializer. These behaviors make it easy to migrate between
535
+ serializer without invalidating the entire cache.
536
+
537
+ *Jonathan Hefner*
538
+
539
+ * `Object#deep_dup` no longer duplicate named classes and modules.
540
+
541
+ Before:
542
+
543
+ ```ruby
544
+ hash = { class: Object, module: Kernel }
545
+ hash.deep_dup # => {:class=>#<Class:0x00000001063ffc80>, :module=>#<Module:0x00000001063ffa00>}
546
+ ```
547
+
548
+ After:
549
+
550
+ ```ruby
551
+ hash = { class: Object, module: Kernel }
552
+ hash.deep_dup # => {:class=>Object, :module=>Kernel}
553
+ ```
554
+
555
+ *Jean Boussier*
556
+
557
+ * Consistently raise an `ArgumentError` if the `ActiveSupport::Cache` key is blank.
558
+
559
+ *Joshua Young*
560
+
561
+ * Deprecate usage of the singleton `ActiveSupport::Deprecation`.
562
+
563
+ All usage of `ActiveSupport::Deprecation` as a singleton is deprecated, the most common one being
564
+ `ActiveSupport::Deprecation.warn`. Gem authors should now create their own deprecator (`ActiveSupport::Deprecation`
565
+ object), and use it to emit deprecation warnings.
566
+
567
+ Calling any of the following without specifying a deprecator argument is also deprecated:
568
+ * Module.deprecate
569
+ * deprecate_constant
570
+ * DeprecatedObjectProxy
571
+ * DeprecatedInstanceVariableProxy
572
+ * DeprecatedConstantProxy
573
+ * deprecation-related test assertions
574
+
575
+ Use of `ActiveSupport::Deprecation.silence` and configuration methods like `behavior=`, `disallowed_behavior=`,
576
+ `disallowed_warnings=` should now be aimed at the [application's deprecators](https://api.rubyonrails.org/classes/Rails/Application.html#method-i-deprecators).
577
+
578
+ ```ruby
579
+ Rails.application.deprecators.silence do
580
+ # code that emits deprecation warnings
581
+ end
582
+ ```
583
+
584
+ If your gem has a Railtie or Engine, it's encouraged to add your deprecator to the application's deprecators, that
585
+ way the deprecation related configuration options will apply to it as well, e.g.
586
+ `config.active_support.report_deprecations` set to `false` in the production environment will also disable your
587
+ deprecator.
588
+
589
+ ```ruby
590
+ initializer "my_gem.deprecator" do |app|
591
+ app.deprecators[:my_gem] = MyGem.deprecator
592
+ end
593
+ ```
594
+
595
+ *Étienne Barrié*
596
+
597
+ * Add `Object#with` to set and restore public attributes around a block
598
+
599
+ ```ruby
600
+ client.timeout # => 5
601
+ client.with(timeout: 1) do
602
+ client.timeout # => 1
603
+ end
604
+ client.timeout # => 5
605
+ ```
606
+
607
+ *Jean Boussier*
608
+
609
+ * Remove deprecated support to generate incorrect RFC 4122 UUIDs when providing a namespace ID that is not one of the
610
+ constants defined on `Digest::UUID`.
50
611
 
51
612
  *Rafael Mendonça França*
52
613
 
53
- * Remove deprecated file `active_support/core_ext/hash/transform_values`.
614
+ * Deprecate `config.active_support.use_rfc4122_namespaced_uuids`.
54
615
 
55
616
  *Rafael Mendonça França*
56
617
 
57
- * Remove deprecated file `active_support/core_ext/hash/compact`.
618
+ * Remove implicit conversion of objects into `String` by `ActiveSupport::SafeBuffer`.
58
619
 
59
620
  *Rafael Mendonça França*
60
621
 
61
- * Remove deprecated file `active_support/core_ext/array/prepend_and_append`.
622
+ * Remove deprecated `active_support/core_ext/range/include_time_with_zone` file.
62
623
 
63
624
  *Rafael Mendonça França*
64
625
 
65
- * Remove deprecated file `active_support/core_ext/numeric/inquiry`.
626
+ * Deprecate `config.active_support.remove_deprecated_time_with_zone_name`.
66
627
 
67
628
  *Rafael Mendonça França*
68
629
 
69
- * Remove deprecated file `active_support/core_ext/module/reachable`.
630
+ * Remove deprecated override of `ActiveSupport::TimeWithZone.name`.
70
631
 
71
632
  *Rafael Mendonça França*
72
633
 
73
- * Remove deprecated `Module#parent_name`, `Module#parent` and `Module#parents`.
634
+ * Deprecate `config.active_support.disable_to_s_conversion`.
74
635
 
75
636
  *Rafael Mendonça França*
76
637
 
77
- * Remove deprecated `ActiveSupport::LoggerThreadSafeLevel#after_initialize`.
638
+ * Remove deprecated option to passing a format to `#to_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
639
+ `BigDecimal`, `Float` and, `Integer`.
78
640
 
79
641
  *Rafael Mendonça França*
80
642
 
81
- * Remove deprecated `LoggerSilence` constant.
643
+ * Remove deprecated `ActiveSupport::PerThreadRegistry`.
82
644
 
83
645
  *Rafael Mendonça França*
84
646
 
85
- * Remove deprecated fallback to `I18n.default_local` when `config.i18n.fallbacks` is empty.
647
+ * Remove deprecated override of `Enumerable#sum`.
86
648
 
87
649
  *Rafael Mendonça França*
88
650
 
89
- * Remove entries from local cache on `RedisCacheStore#delete_matched`
651
+ * Deprecated initializing a `ActiveSupport::Cache::MemCacheStore` with an instance of `Dalli::Client`.
90
652
 
91
- Fixes #38627
653
+ 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.
92
654
 
93
- *ojab*
655
+ *aledustet*
94
656
 
95
- * Speed up `ActiveSupport::SecurityUtils.fixed_length_secure_compare` by using
96
- `OpenSSL.fixed_length_secure_compare`, if available.
657
+ * Stub `Time.new()` in `TimeHelpers#travel_to`
97
658
 
98
- *Nate Matykiewicz*
659
+ ```ruby
660
+ travel_to Time.new(2004, 11, 24) do
661
+ # Inside the `travel_to` block `Time.new` is stubbed
662
+ assert_equal 2004, Time.new.year
663
+ end
664
+ ```
99
665
 
100
- * `ActiveSupport::Cache::MemCacheStore` now checks `ENV["MEMCACHE_SERVERS"]` before falling back to `"localhost:11211"` if configured without any addresses.
666
+ *fatkodima*
101
667
 
102
- ```ruby
103
- config.cache_store = :mem_cache_store
668
+ * Raise `ActiveSupport::MessageEncryptor::InvalidMessage` from
669
+ `ActiveSupport::MessageEncryptor#decrypt_and_verify` regardless of cipher.
670
+ Previously, when a `MessageEncryptor` was using a non-AEAD cipher such as
671
+ AES-256-CBC, a corrupt or tampered message would raise
672
+ `ActiveSupport::MessageVerifier::InvalidSignature`. Now, all ciphers raise
673
+ the same error:
674
+
675
+ ```ruby
676
+ encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-gcm")
677
+ message = encryptor.encrypt_and_sign("message")
678
+ encryptor.decrypt_and_verify(message.next)
679
+ # => raises ActiveSupport::MessageEncryptor::InvalidMessage
680
+
681
+ encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-cbc")
682
+ message = encryptor.encrypt_and_sign("message")
683
+ encryptor.decrypt_and_verify(message.next)
684
+ # BEFORE:
685
+ # => raises ActiveSupport::MessageVerifier::InvalidSignature
686
+ # AFTER:
687
+ # => raises ActiveSupport::MessageEncryptor::InvalidMessage
688
+ ```
689
+
690
+ *Jonathan Hefner*
691
+
692
+ * Support `nil` original values when using `ActiveSupport::MessageVerifier#verify`.
693
+ Previously, `MessageVerifier#verify` did not work with `nil` original
694
+ values, though both `MessageVerifier#verified` and
695
+ `MessageEncryptor#decrypt_and_verify` do:
104
696
 
105
- # is now equivalent to
697
+ ```ruby
698
+ encryptor = ActiveSupport::MessageEncryptor.new(secret)
699
+ message = encryptor.encrypt_and_sign(nil)
106
700
 
107
- config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211"
701
+ encryptor.decrypt_and_verify(message)
702
+ # => nil
108
703
 
109
- # instead of
704
+ verifier = ActiveSupport::MessageVerifier.new(secret)
705
+ message = verifier.generate(nil)
110
706
 
111
- config.cache_store = :mem_cache_store, "localhost:11211" # ignores ENV["MEMCACHE_SERVERS"]
707
+ verifier.verified(message)
708
+ # => nil
709
+
710
+ verifier.verify(message)
711
+ # BEFORE:
712
+ # => raises ActiveSupport::MessageVerifier::InvalidSignature
713
+ # AFTER:
714
+ # => nil
715
+ ```
716
+
717
+ *Jonathan Hefner*
718
+
719
+ * Maintain `html_safe?` on html_safe strings when sliced with `slice`, `slice!`, or `chr` method.
720
+
721
+ Previously, `html_safe?` was only maintained when the html_safe strings were sliced
722
+ with `[]` method. Now, `slice`, `slice!`, and `chr` methods will maintain `html_safe?` like `[]` method.
723
+
724
+ ```ruby
725
+ string = "<div>test</div>".html_safe
726
+ string.slice(0, 1).html_safe? # => true
727
+ string.slice!(0, 1).html_safe? # => true
728
+ # maintain html_safe? after the slice!
729
+ string.html_safe? # => true
730
+ string.chr.html_safe? # => true
112
731
  ```
113
732
 
114
- *Sam Bostock*
733
+ *Michael Go*
115
734
 
116
- * `ActiveSupport::Subscriber#attach_to` now accepts an `inherit_all:` argument. When set to true,
117
- it allows a subscriber to receive events for methods defined in the subscriber's ancestor class(es).
735
+ * Add `Object#in?` support for open ranges.
118
736
 
119
737
  ```ruby
120
- class ActionControllerSubscriber < ActiveSupport::Subscriber
121
- attach_to :action_controller
738
+ assert Date.today.in?(..Date.tomorrow)
739
+ assert_not Date.today.in?(Date.tomorrow..)
740
+ ```
122
741
 
123
- def start_processing(event)
124
- info "Processing by #{event.payload[:controller]}##{event.payload[:action]} as #{format}"
125
- end
742
+ *Ignacio Galindo*
126
743
 
127
- def redirect_to(event)
128
- info { "Redirected to #{event.payload[:location]}" }
129
- end
130
- end
744
+ * `config.i18n.raise_on_missing_translations = true` now raises on any missing translation.
131
745
 
132
- # We detach ActionControllerSubscriber from the :action_controller namespace so that our CustomActionControllerSubscriber
133
- # can provide its own instrumentation for certain events in the namespace
134
- ActionControllerSubscriber.detach_from(:action_controller)
746
+ Previously it would only raise when called in a view or controller. Now it will raise
747
+ anytime `I18n.t` is provided an unrecognised key.
135
748
 
136
- class CustomActionControllerSubscriber < ActionControllerSubscriber
137
- attach_to :action_controller, inherit_all: true
749
+ If you do not want this behaviour, you can customise the i18n exception handler. See the
750
+ upgrading guide or i18n guide for more information.
138
751
 
139
- def start_processing(event)
140
- info "A custom response to start_processing events"
141
- end
752
+ *Alex Ghiculescu*
142
753
 
143
- # => CustomActionControllerSubscriber will process events for "start_processing.action_controller" notifications
144
- # using its own #start_processing implementation, while retaining ActionControllerSubscriber's instrumentation
145
- # for "redirect_to.action_controller" notifications
754
+ * `ActiveSupport::CurrentAttributes` now raises if a restricted attribute name is used.
755
+
756
+ Attributes such as `set` and `reset` cannot be used as they clash with the
757
+ `CurrentAttributes` public API.
758
+
759
+ *Alex Ghiculescu*
760
+
761
+ * `HashWithIndifferentAccess#transform_keys` now takes a Hash argument, just
762
+ as Ruby's `Hash#transform_keys` does.
763
+
764
+ *Akira Matsuda*
765
+
766
+ * `delegate` now defines method with proper arity when delegating to a Class.
767
+ With this change, it defines faster method (3.5x faster with no argument).
768
+ However, in order to gain this benefit, the delegation target method has to
769
+ be defined before declaring the delegation.
770
+
771
+ ```ruby
772
+ # This defines 3.5 times faster method than before
773
+ class C
774
+ def self.x() end
775
+ delegate :x, to: :class
776
+ end
777
+
778
+ class C
779
+ # This works but silently falls back to old behavior because
780
+ # `delegate` cannot find the definition of `x`
781
+ delegate :x, to: :class
782
+ def self.x() end
146
783
  end
147
784
  ```
148
785
 
149
- *Adrianna Chang*
786
+ *Akira Matsuda*
150
787
 
151
- * Allow the digest class used to generate non-sensitive digests to be configured with `config.active_support.hash_digest_class`.
788
+ * `assert_difference` message now includes what changed.
789
+
790
+ This makes it easier to debug non-obvious failures.
791
+
792
+ Before:
152
793
 
153
- `config.active_support.use_sha1_digests` is deprecated in favour of `config.active_support.hash_digest_class = ::Digest::SHA1`.
794
+ ```
795
+ "User.count" didn't change by 32.
796
+ Expected: 1611
797
+ Actual: 1579
798
+ ```
154
799
 
155
- *Dirkjan Bussink*
800
+ After:
156
801
 
157
- * Fix bug to make memcached write_entry expire correctly with unless_exist
802
+ ```
803
+ "User.count" didn't change by 32, but by 0.
804
+ Expected: 1611
805
+ Actual: 1579
806
+ ```
158
807
 
159
- *Jye Lee*
808
+ *Alex Ghiculescu*
160
809
 
161
- * Add `ActiveSupport::Duration` conversion methods
810
+ * Add ability to match exception messages to `assert_raises` assertion
162
811
 
163
- `in_seconds`, `in_minutes`, `in_hours`, `in_days`, `in_weeks`, `in_months`, and `in_years` return the respective duration covered.
812
+ Instead of this
813
+ ```ruby
814
+ error = assert_raises(ArgumentError) do
815
+ perform_service(param: 'exception')
816
+ end
817
+ assert_match(/incorrect param/i, error.message)
818
+ ```
164
819
 
165
- *Jason York*
820
+ you can now write this
821
+ ```ruby
822
+ assert_raises(ArgumentError, match: /incorrect param/i) do
823
+ perform_service(param: 'exception')
824
+ end
825
+ ```
166
826
 
167
- * Fixed issue in `ActiveSupport::Cache::RedisCacheStore` not passing options
168
- to `read_multi` causing `fetch_multi` to not work properly
827
+ *fatkodima*
169
828
 
170
- *Rajesh Sharma*
829
+ * Add `Rails.env.local?` shorthand for `Rails.env.development? || Rails.env.test?`.
171
830
 
172
- * Fixed issue in `ActiveSupport::Cache::MemCacheStore` which caused duplicate compression,
173
- and caused the provided `compression_threshold` to not be respected.
831
+ *DHH*
174
832
 
175
- *Max Gurewitz*
833
+ * `ActiveSupport::Testing::TimeHelpers` now accepts named `with_usec` argument
834
+ to `freeze_time`, `travel`, and `travel_to` methods. Passing true prevents
835
+ truncating the destination time with `change(usec: 0)`.
176
836
 
177
- * Prevent `RedisCacheStore` and `MemCacheStore` from performing compression
178
- when reading entries written with `raw: true`.
837
+ *KevSlashNull*, and *serprex*
179
838
 
180
- *Max Gurewitz*
839
+ * `ActiveSupport::CurrentAttributes.resets` now accepts a method name
181
840
 
182
- * `URI.parser` is deprecated and will be removed in Rails 6.2. Use
183
- `URI::DEFAULT_PARSER` instead.
841
+ The block API is still the recommended approach, but now both APIs are supported:
184
842
 
185
- *Jean Boussier*
843
+ ```ruby
844
+ class Current < ActiveSupport::CurrentAttributes
845
+ resets { Time.zone = nil }
846
+ resets :clear_time_zone
847
+ end
848
+ ```
849
+
850
+ *Alex Ghiculescu*
851
+
852
+ * Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
853
+
854
+ Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
855
+ process closed the read end, wrote to it, and then terminated (which
856
+ presumably closed the file descriptors on its end). The parent process
857
+ closed the write end, read from it, and returned, never closing the read
858
+ end.
186
859
 
187
- * `require_dependency` has been documented to be _obsolete_ in `:zeitwerk`
188
- mode. The method is not deprecated as such (yet), but applications are
189
- encouraged to not use it.
860
+ This resulted in an accumulation of open file descriptors, which could
861
+ cause errors if the limit is reached.
190
862
 
191
- In `:zeitwerk` mode, semantics match Ruby's and you do not need to be
192
- defensive with load order. Just refer to classes and modules normally. If
193
- the constant name is dynamic, camelize if needed, and constantize.
863
+ *Sam Bostock*
194
864
 
195
- *Xavier Noria*
865
+ * Fix `Time#change` and `Time#advance` for times around the end of Daylight
866
+ Saving Time.
196
867
 
197
- * Add 3rd person aliases of `Symbol#start_with?` and `Symbol#end_with?`.
868
+ Previously, when `Time#change` or `Time#advance` constructed a time inside
869
+ the final stretch of Daylight Saving Time (DST), the non-DST offset would
870
+ always be chosen for local times:
198
871
 
199
872
  ```ruby
200
- :foo.starts_with?("f") # => true
201
- :foo.ends_with?("o") # => true
873
+ # DST ended just before 2021-11-07 2:00:00 AM in US/Eastern.
874
+ ENV["TZ"] = "US/Eastern"
875
+
876
+ time = Time.local(2021, 11, 07, 00, 59, 59) + 1
877
+ # => 2021-11-07 01:00:00 -0400
878
+ time.change(day: 07)
879
+ # => 2021-11-07 01:00:00 -0500
880
+ time.advance(seconds: 0)
881
+ # => 2021-11-07 01:00:00 -0500
882
+
883
+ time = Time.local(2021, 11, 06, 01, 00, 00)
884
+ # => 2021-11-06 01:00:00 -0400
885
+ time.change(day: 07)
886
+ # => 2021-11-07 01:00:00 -0500
887
+ time.advance(days: 1)
888
+ # => 2021-11-07 01:00:00 -0500
202
889
  ```
203
890
 
204
- *Ryuta Kamizono*
891
+ And the DST offset would always be chosen for times with a `TimeZone`
892
+ object:
205
893
 
206
- * Add override of unary plus for `ActiveSupport::Duration`.
894
+ ```ruby
895
+ Time.zone = "US/Eastern"
896
+
897
+ time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
898
+ # => 2021-11-07 01:00:00 -0500
899
+ time.change(day: 07)
900
+ # => 2021-11-07 01:00:00 -0400
901
+ time.advance(seconds: 0)
902
+ # => 2021-11-07 01:00:00 -0400
903
+
904
+ time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
905
+ # => 2021-11-08 01:00:00 -0500
906
+ time.change(day: 07)
907
+ # => 2021-11-07 01:00:00 -0400
908
+ time.advance(days: -1)
909
+ # => 2021-11-07 01:00:00 -0400
910
+ ```
207
911
 
208
- `+ 1.second` is now identical to `+1.second` to prevent errors
209
- where a seemingly innocent change of formatting leads to a change in the code behavior.
912
+ Now, `Time#change` and `Time#advance` will choose the offset that matches
913
+ the original time's offset when possible:
210
914
 
211
- Before:
212
915
  ```ruby
213
- +1.second.class
214
- # => ActiveSupport::Duration
215
- (+ 1.second).class
216
- # => Integer
916
+ ENV["TZ"] = "US/Eastern"
917
+
918
+ time = Time.local(2021, 11, 07, 00, 59, 59) + 1
919
+ # => 2021-11-07 01:00:00 -0400
920
+ time.change(day: 07)
921
+ # => 2021-11-07 01:00:00 -0400
922
+ time.advance(seconds: 0)
923
+ # => 2021-11-07 01:00:00 -0400
924
+
925
+ time = Time.local(2021, 11, 06, 01, 00, 00)
926
+ # => 2021-11-06 01:00:00 -0400
927
+ time.change(day: 07)
928
+ # => 2021-11-07 01:00:00 -0400
929
+ time.advance(days: 1)
930
+ # => 2021-11-07 01:00:00 -0400
931
+
932
+ Time.zone = "US/Eastern"
933
+
934
+ time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
935
+ # => 2021-11-07 01:00:00 -0500
936
+ time.change(day: 07)
937
+ # => 2021-11-07 01:00:00 -0500
938
+ time.advance(seconds: 0)
939
+ # => 2021-11-07 01:00:00 -0500
940
+
941
+ time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
942
+ # => 2021-11-08 01:00:00 -0500
943
+ time.change(day: 07)
944
+ # => 2021-11-07 01:00:00 -0500
945
+ time.advance(days: -1)
946
+ # => 2021-11-07 01:00:00 -0500
217
947
  ```
218
948
 
219
- After:
949
+ *Kevin Hall*, *Takayoshi Nishida*, and *Jonathan Hefner*
950
+
951
+ * Fix MemoryStore to preserve entries TTL when incrementing or decrementing
952
+
953
+ This is to be more consistent with how MemCachedStore and RedisCacheStore behaves.
954
+
955
+ *Jean Boussier*
956
+
957
+ * `Rails.error.handle` and `Rails.error.record` filter now by multiple error classes.
958
+
220
959
  ```ruby
221
- +1.second.class
222
- # => ActiveSupport::Duration
223
- (+ 1.second).class
224
- # => ActiveSupport::Duration
960
+ Rails.error.handle(IOError, ArgumentError) do
961
+ 1 + '1' # raises TypeError
962
+ end
963
+ 1 + 1 # TypeErrors are not IOErrors or ArgumentError, so this will *not* be handled
225
964
  ```
226
965
 
227
- Fixes #39079.
966
+ *Martin Spickermann*
228
967
 
229
- *Roman Kushnir*
968
+ * `Class#subclasses` and `Class#descendants` now automatically filter reloaded classes.
230
969
 
231
- * Add subsec to `ActiveSupport::TimeWithZone#inspect`.
970
+ Previously they could return old implementations of reloadable classes that have been
971
+ dereferenced but not yet garbage collected.
232
972
 
233
- Before:
973
+ They now automatically filter such classes like `DescendantTracker#subclasses` and
974
+ `DescendantTracker#descendants`.
234
975
 
235
- Time.at(1498099140).in_time_zone.inspect
236
- # => "Thu, 22 Jun 2017 02:39:00 UTC +00:00"
237
- Time.at(1498099140, 123456780, :nsec).in_time_zone.inspect
238
- # => "Thu, 22 Jun 2017 02:39:00 UTC +00:00"
239
- Time.at(1498099140 + Rational("1/3")).in_time_zone.inspect
240
- # => "Thu, 22 Jun 2017 02:39:00 UTC +00:00"
976
+ *Jean Boussier*
241
977
 
242
- After:
978
+ * `Rails.error.report` now marks errors as reported to avoid reporting them twice.
243
979
 
244
- Time.at(1498099140).in_time_zone.inspect
245
- # => "Thu, 22 Jun 2017 02:39:00.000000000 UTC +00:00"
246
- Time.at(1498099140, 123456780, :nsec).in_time_zone.inspect
247
- # => "Thu, 22 Jun 2017 02:39:00.123456780 UTC +00:00"
248
- Time.at(1498099140 + Rational("1/3")).in_time_zone.inspect
249
- # => "Thu, 22 Jun 2017 02:39:00.333333333 UTC +00:00"
980
+ In some cases, users might want to report errors explicitly with some extra context
981
+ before letting it bubble up.
982
+
983
+ This also allows to safely catch and report errors outside of the execution context.
984
+
985
+ *Jean Boussier*
250
986
 
251
- *akinomaeni*
987
+ * Add `assert_error_reported` and `assert_no_error_reported`
252
988
 
253
- * Calling `ActiveSupport::TaggedLogging#tagged` without a block now returns a tagged logger.
989
+ Allows to easily asserts an error happened but was handled
254
990
 
255
991
  ```ruby
256
- logger.tagged("BCX").info("Funky time!") # => [BCX] Funky time!
992
+ report = assert_error_reported(IOError) do
993
+ # ...
994
+ end
995
+ assert_equal "Oops", report.error.message
996
+ assert_equal "admin", report.context[:section]
997
+ assert_equal :warning, report.severity
998
+ assert_predicate report, :handled?
257
999
  ```
258
1000
 
259
- *Eugene Kenny*
1001
+ *Jean Boussier*
260
1002
 
261
- * Align `Range#cover?` extension behavior with Ruby behavior for backwards ranges.
1003
+ * `ActiveSupport::Deprecation` behavior callbacks can now receive the
1004
+ deprecator instance as an argument. This makes it easier for such callbacks
1005
+ to change their behavior based on the deprecator's state. For example,
1006
+ based on the deprecator's `debug` flag.
262
1007
 
263
- `(1..10).cover?(5..3)` now returns `false`, as it does in plain Ruby.
1008
+ 3-arity and splat-args callbacks such as the following will now be passed
1009
+ the deprecator instance as their third argument:
264
1010
 
265
- Also update `#include?` and `#===` behavior to match.
1011
+ * `->(message, callstack, deprecator) { ... }`
1012
+ * `->(*args) { ... }`
1013
+ * `->(message, *other_args) { ... }`
266
1014
 
267
- *Michael Groeneman*
1015
+ 2-arity and 4-arity callbacks such as the following will continue to behave
1016
+ the same as before:
268
1017
 
269
- * Update to TZInfo v2.0.0.
1018
+ * `->(message, callstack) { ... }`
1019
+ * `->(message, callstack, deprecation_horizon, gem_name) { ... }`
1020
+ * `->(message, callstack, *deprecation_details) { ... }`
270
1021
 
271
- This changes the output of `ActiveSupport::TimeZone.utc_to_local`, but
272
- can be controlled with the
273
- `ActiveSupport.utc_to_local_returns_utc_offset_times` config.
1022
+ *Jonathan Hefner*
274
1023
 
275
- New Rails 6.1 apps have it enabled by default, existing apps can upgrade
276
- via the config in config/initializers/new_framework_defaults_6_1.rb
1024
+ * `ActiveSupport::Deprecation#disallowed_warnings` now affects the instance on
1025
+ which it is configured.
277
1026
 
278
- See the `utc_to_local_returns_utc_offset_times` documentation for details.
1027
+ This means that individual `ActiveSupport::Deprecation` instances can be
1028
+ configured with their own disallowed warnings, and the global
1029
+ `ActiveSupport::Deprecation.disallowed_warnings` now only affects the global
1030
+ `ActiveSupport::Deprecation.warn`.
279
1031
 
280
- *Phil Ross*, *Jared Beck*
1032
+ **Before**
281
1033
 
282
- * Add Date and Time `#yesterday?` and `#tomorrow?` alongside `#today?`.
1034
+ ```ruby
1035
+ ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
1036
+ deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
1037
+ deprecator.disallowed_warnings = ["bar"]
1038
+
1039
+ ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
1040
+ ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
1041
+ deprecator.warn("foo") # => raise ActiveSupport::DeprecationException
1042
+ deprecator.warn("bar") # => print "DEPRECATION WARNING: bar"
1043
+ ```
283
1044
 
284
- Aliased to `#prev_day?` and `#next_day?` to match the existing `#prev/next_day` methods.
1045
+ **After**
285
1046
 
286
- *Jatin Dhankhar*
1047
+ ```ruby
1048
+ ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
1049
+ deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
1050
+ deprecator.disallowed_warnings = ["bar"]
1051
+
1052
+ ActiveSupport::Deprecation.warn("foo") # => raise ActiveSupport::DeprecationException
1053
+ ActiveSupport::Deprecation.warn("bar") # => print "DEPRECATION WARNING: bar"
1054
+ deprecator.warn("foo") # => print "DEPRECATION WARNING: foo"
1055
+ deprecator.warn("bar") # => raise ActiveSupport::DeprecationException
1056
+ ```
287
1057
 
288
- * Add `Enumerable#pick` to complement `ActiveRecord::Relation#pick`.
1058
+ Note that global `ActiveSupport::Deprecation` methods such as `ActiveSupport::Deprecation.warn`
1059
+ and `ActiveSupport::Deprecation.disallowed_warnings` have been deprecated.
289
1060
 
290
- *Eugene Kenny*
1061
+ *Jonathan Hefner*
291
1062
 
292
- * [Breaking change] `ActiveSupport::Callbacks#halted_callback_hook` now receive a 2nd argument:
1063
+ * Add italic and underline support to `ActiveSupport::LogSubscriber#color`
293
1064
 
294
- `ActiveSupport::Callbacks#halted_callback_hook` now receive the name of the callback
295
- being halted as second argument.
296
- This change will allow you to differentiate which callbacks halted the chain
297
- and act accordingly.
1065
+ Previously, only bold text was supported via a positional argument.
1066
+ This allows for bold, italic, and underline options to be specified
1067
+ for colored logs.
298
1068
 
299
1069
  ```ruby
300
- class Book < ApplicationRecord
301
- before_save { throw(:abort) }
302
- before_create { throw(:abort) }
1070
+ info color("Hello world!", :red, bold: true, underline: true)
1071
+ ```
303
1072
 
304
- def halted_callback_hook(filter, callback_name)
305
- Rails.logger.info("Book couldn't be #{callback_name}d")
306
- end
1073
+ *Gannon McGibbon*
307
1074
 
308
- Book.create # => "Book couldn't be created"
309
- book.save # => "Book couldn't be saved"
310
- end
311
- ```
1075
+ * Add `String#downcase_first` method.
312
1076
 
313
- *Edouard Chin*
1077
+ This method is the corollary of `String#upcase_first`.
314
1078
 
315
- * Support `prepend` with `ActiveSupport::Concern`.
1079
+ *Mark Schneider*
316
1080
 
317
- Allows a module with `extend ActiveSupport::Concern` to be prepended.
1081
+ * `thread_mattr_accessor` will call `.dup.freeze` on non-frozen default values.
318
1082
 
319
- module Imposter
320
- extend ActiveSupport::Concern
1083
+ This provides a basic level of protection against different threads trying
1084
+ to mutate a shared default object.
321
1085
 
322
- # Same as `included`, except only run when prepended.
323
- prepended do
324
- end
325
- end
1086
+ *Jonathan Hefner*
326
1087
 
327
- class Person
328
- prepend Imposter
329
- end
1088
+ * Add `raise_on_invalid_cache_expiration_time` config to `ActiveSupport::Cache::Store`
330
1089
 
331
- Class methods are prepended to the base class, concerning is also
332
- updated: `concerning :Imposter, prepend: true do`.
1090
+ Specifies if an `ArgumentError` should be raised if `Rails.cache` `fetch` or
1091
+ `write` are given an invalid `expires_at` or `expires_in` time.
333
1092
 
334
- *Jason Karns*, *Elia Schito*
1093
+ Options are `true`, and `false`. If `false`, the exception will be reported
1094
+ as `handled` and logged instead. Defaults to `true` if `config.load_defaults >= 7.1`.
335
1095
 
336
- * Deprecate using `Range#include?` method to check the inclusion of a value
337
- in a date time range. It is recommended to use `Range#cover?` method
338
- instead of `Range#include?` to check the inclusion of a value
339
- in a date time range.
1096
+ *Trevor Turk*
340
1097
 
341
- *Vishal Telangre*
1098
+ * `ActiveSupport::Cache::Store#fetch` now passes an options accessor to the block.
342
1099
 
343
- * Support added for a `round_mode` parameter, in all number helpers. (See: `BigDecimal::mode`.)
1100
+ It makes possible to override cache options:
344
1101
 
345
- ```ruby
346
- number_to_currency(1234567890.50, precision: 0, round_mode: :half_down) # => "$1,234,567,890"
347
- number_to_percentage(302.24398923423, precision: 5, round_mode: :down) # => "302.24398%"
348
- number_to_rounded(389.32314, precision: 0, round_mode: :ceil) # => "390"
349
- number_to_human_size(483989, precision: 2, round_mode: :up) # => "480 KB"
350
- number_to_human(489939, precision: 2, round_mode: :floor) # => "480 Thousand"
1102
+ Rails.cache.fetch("3rd-party-token") do |name, options|
1103
+ token = fetch_token_from_remote
1104
+ # set cache's TTL to match token's TTL
1105
+ options.expires_in = token.expires_in
1106
+ token
1107
+ end
351
1108
 
352
- 485000.to_s(:human, precision: 2, round_mode: :half_even) # => "480 Thousand"
353
- ```
1109
+ *Andrii Gladkyi*, *Jean Boussier*
354
1110
 
355
- *Tom Lord*
1111
+ * `default` option of `thread_mattr_accessor` now applies through inheritance and
1112
+ also across new threads.
356
1113
 
357
- * `Array#to_sentence` no longer returns a frozen string.
1114
+ Previously, the `default` value provided was set only at the moment of defining
1115
+ the attribute writer, which would cause the attribute to be uninitialized in
1116
+ descendants and in other threads.
358
1117
 
359
- Before:
1118
+ Fixes #43312.
360
1119
 
361
- ['one', 'two'].to_sentence.frozen?
362
- # => true
1120
+ *Thierry Deo*
363
1121
 
364
- After:
1122
+ * Redis cache store is now compatible with redis-rb 5.0.
365
1123
 
366
- ['one', 'two'].to_sentence.frozen?
367
- # => false
1124
+ *Jean Boussier*
368
1125
 
369
- *Nicolas Dular*
1126
+ * Add `skip_nil:` support to `ActiveSupport::Cache::Store#fetch_multi`.
370
1127
 
371
- * When an instance of `ActiveSupport::Duration` is converted to an `iso8601` duration string, if `weeks` are mixed with `date` parts, the `week` part will be converted to days.
372
- This keeps the parser and serializer on the same page.
1128
+ *Daniel Alfaro*
373
1129
 
374
- ```ruby
375
- duration = ActiveSupport::Duration.build(1000000)
376
- # 1 week, 4 days, 13 hours, 46 minutes, and 40.0 seconds
1130
+ * Add `quarter` method to date/time
377
1131
 
378
- duration_iso = duration.iso8601
379
- # P11DT13H46M40S
1132
+ *Matt Swanson*
380
1133
 
381
- ActiveSupport::Duration.parse(duration_iso)
382
- # 11 days, 13 hours, 46 minutes, and 40 seconds
1134
+ * Fix `NoMethodError` on custom `ActiveSupport::Deprecation` behavior.
383
1135
 
384
- duration = ActiveSupport::Duration.build(604800)
385
- # 1 week
1136
+ `ActiveSupport::Deprecation.behavior=` was supposed to accept any object
1137
+ that responds to `call`, but in fact its internal implementation assumed that
1138
+ this object could respond to `arity`, so it was restricted to only `Proc` objects.
386
1139
 
387
- duration_iso = duration.iso8601
388
- # P1W
1140
+ This change removes this `arity` restriction of custom behaviors.
389
1141
 
390
- ActiveSupport::Duration.parse(duration_iso)
391
- # 1 week
392
- ```
1142
+ *Ryo Nakamura*
393
1143
 
394
- *Abhishek Sarkar*
1144
+ * Support `:url_safe` option for `MessageEncryptor`.
395
1145
 
396
- * Add block support to `ActiveSupport::Testing::TimeHelpers#travel_back`.
1146
+ The `MessageEncryptor` constructor now accepts a `:url_safe` option, similar
1147
+ to the `MessageVerifier` constructor. When enabled, this option ensures
1148
+ that messages use a URL-safe encoding.
397
1149
 
398
- *Tim Masliuchenko*
1150
+ *Jonathan Hefner*
399
1151
 
400
- * Update `ActiveSupport::Messages::Metadata#fresh?` to work for cookies with expiry set when
401
- `ActiveSupport.parse_json_times = true`.
1152
+ * Add `url_safe` option to `ActiveSupport::MessageVerifier` initializer
402
1153
 
403
- *Christian Gregg*
1154
+ `ActiveSupport::MessageVerifier.new` now takes optional `url_safe` argument.
1155
+ It can generate URL-safe strings by passing `url_safe: true`.
404
1156
 
405
- * Support symbolic links for `content_path` in `ActiveSupport::EncryptedFile`.
1157
+ ```ruby
1158
+ verifier = ActiveSupport::MessageVerifier.new(url_safe: true)
1159
+ message = verifier.generate(data) # => URL-safe string
1160
+ ```
406
1161
 
407
- *Takumi Shotoku*
1162
+ This option is `false` by default to be backwards compatible.
408
1163
 
409
- * Improve `Range#===`, `Range#include?`, and `Range#cover?` to work with beginless (startless)
410
- and endless range targets.
1164
+ *Shouichi Kamiya*
411
1165
 
412
- *Allen Hsu*, *Andrew Hodgkinson*
1166
+ * Enable connection pooling by default for `MemCacheStore` and `RedisCacheStore`.
413
1167
 
414
- * Don't use `Process#clock_gettime(CLOCK_THREAD_CPUTIME_ID)` on Solaris.
1168
+ If you want to disable connection pooling, set `:pool` option to `false` when configuring the cache store:
415
1169
 
416
- *Iain Beeston*
1170
+ ```ruby
1171
+ config.cache_store = :mem_cache_store, "cache.example.com", pool: false
1172
+ ```
417
1173
 
418
- * Prevent `ActiveSupport::Duration.build(value)` from creating instances of
419
- `ActiveSupport::Duration` unless `value` is of type `Numeric`.
1174
+ *fatkodima*
420
1175
 
421
- Addresses the errant set of behaviours described in #37012 where
422
- `ActiveSupport::Duration` comparisons would fail confusingly
423
- or return unexpected results when comparing durations built from instances of `String`.
1176
+ * Add `force:` support to `ActiveSupport::Cache::Store#fetch_multi`.
424
1177
 
425
- Before:
1178
+ *fatkodima*
426
1179
 
427
- small_duration_from_string = ActiveSupport::Duration.build('9')
428
- large_duration_from_string = ActiveSupport::Duration.build('100000000000000')
429
- small_duration_from_int = ActiveSupport::Duration.build(9)
1180
+ * Deprecated `:pool_size` and `:pool_timeout` options for configuring connection pooling in cache stores.
430
1181
 
431
- large_duration_from_string > small_duration_from_string
432
- # => false
1182
+ Use `pool: true` to enable pooling with default settings:
433
1183
 
434
- small_duration_from_string == small_duration_from_int
435
- # => false
1184
+ ```ruby
1185
+ config.cache_store = :redis_cache_store, pool: true
1186
+ ```
436
1187
 
437
- small_duration_from_int < large_duration_from_string
438
- # => ArgumentError (comparison of ActiveSupport::Duration::Scalar with ActiveSupport::Duration failed)
1188
+ Or pass individual options via `:pool` option:
439
1189
 
440
- large_duration_from_string > small_duration_from_int
441
- # => ArgumentError (comparison of String with ActiveSupport::Duration failed)
1190
+ ```ruby
1191
+ config.cache_store = :redis_cache_store, pool: { size: 10, timeout: 2 }
1192
+ ```
442
1193
 
443
- After:
1194
+ *fatkodima*
444
1195
 
445
- small_duration_from_string = ActiveSupport::Duration.build('9')
446
- # => TypeError (can't build an ActiveSupport::Duration from a String)
1196
+ * Allow #increment and #decrement methods of `ActiveSupport::Cache::Store`
1197
+ subclasses to set new values.
447
1198
 
448
- *Alexei Emam*
1199
+ Previously incrementing or decrementing an unset key would fail and return
1200
+ nil. A default will now be assumed and the key will be created.
449
1201
 
450
- * Add `ActiveSupport::Cache::Store#delete_multi` method to delete multiple keys from the cache store.
1202
+ *Andrej Blagojević*, *Eugene Kenny*
451
1203
 
452
- *Peter Zhu*
1204
+ * Add `skip_nil:` support to `RedisCacheStore`
453
1205
 
454
- * Support multiple arguments in `HashWithIndifferentAccess` for `merge` and `update` methods, to
455
- follow Ruby 2.6 addition.
1206
+ *Joey Paris*
456
1207
 
457
- *Wojciech Wnętrzak*
1208
+ * `ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true)` now
1209
+ correctly writes expired keys.
458
1210
 
459
- * Allow initializing `thread_mattr_*` attributes via `:default` option.
1211
+ *Alan Savage*
460
1212
 
461
- class Scraper
462
- thread_mattr_reader :client, default: Api::Client.new
463
- end
1213
+ * `ActiveSupport::ErrorReporter` now accepts and forward a `source:` parameter.
464
1214
 
465
- *Guilherme Mansur*
1215
+ This allow libraries to signal the origin of the errors, and reporters
1216
+ to easily ignore some sources.
466
1217
 
467
- * Add `compact_blank` for those times when you want to remove #blank? values from
468
- an Enumerable (also `compact_blank!` on Hash, Array, ActionController::Parameters).
1218
+ *Jean Boussier*
469
1219
 
470
- *Dana Sherson*
1220
+ * Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
471
1221
 
472
- * Make ActiveSupport::Logger Fiber-safe.
1222
+ Add the method `ERB::Util.xml_name_escape` to escape dangerous characters
1223
+ in names of tags and names of attributes, following the specification of XML.
473
1224
 
474
- Use `Fiber.current.__id__` in `ActiveSupport::Logger#local_level=` in order
475
- to make log level local to Ruby Fibers in addition to Threads.
1225
+ *Álvaro Martín Fraguas*
476
1226
 
477
- Example:
1227
+ * Respect `ActiveSupport::Logger.new`'s `:formatter` keyword argument
478
1228
 
479
- logger = ActiveSupport::Logger.new(STDOUT)
480
- logger.level = 1
481
- puts "Main is debug? #{logger.debug?}"
1229
+ The stdlib `Logger::new` allows passing a `:formatter` keyword argument to
1230
+ set the logger's formatter. Previously `ActiveSupport::Logger.new` ignored
1231
+ that argument by always setting the formatter to an instance of
1232
+ `ActiveSupport::Logger::SimpleFormatter`.
482
1233
 
483
- Fiber.new {
484
- logger.local_level = 0
485
- puts "Thread is debug? #{logger.debug?}"
486
- }.resume
1234
+ *Steven Harman*
487
1235
 
488
- puts "Main is debug? #{logger.debug?}"
1236
+ * Deprecate preserving the pre-Ruby 2.4 behavior of `to_time`
489
1237
 
490
- Before:
1238
+ With Ruby 2.4+ the default for +to_time+ changed from converting to the
1239
+ local system time to preserving the offset of the receiver. At the time Rails
1240
+ supported older versions of Ruby so a compatibility layer was added to assist
1241
+ in the migration process. From Rails 5.0 new applications have defaulted to
1242
+ the Ruby 2.4+ behavior and since Rails 7.0 now only supports Ruby 2.7+
1243
+ this compatibility layer can be safely removed.
491
1244
 
492
- Main is debug? false
493
- Thread is debug? true
494
- Main is debug? true
1245
+ To minimize any noise generated the deprecation warning only appears when the
1246
+ setting is configured to `false` as that is the only scenario where the
1247
+ removal of the compatibility layer has any effect.
495
1248
 
496
- After:
1249
+ *Andrew White*
497
1250
 
498
- Main is debug? false
499
- Thread is debug? true
500
- Main is debug? false
1251
+ * `Pathname.blank?` only returns true for `Pathname.new("")`
501
1252
 
502
- Fixes #36752.
1253
+ Previously it would end up calling `Pathname#empty?` which returned true
1254
+ if the path existed and was an empty directory or file.
503
1255
 
504
- *Alexander Varnin*
1256
+ That behavior was unlikely to be expected.
505
1257
 
506
- * Allow the `on_rotation` proc used when decrypting/verifying a message to be
507
- passed at the constructor level.
1258
+ *Jean Boussier*
508
1259
 
509
- Before:
1260
+ * Deprecate `Notification::Event`'s `#children` and `#parent_of?`
510
1261
 
511
- crypt = ActiveSupport::MessageEncryptor.new('long_secret')
512
- crypt.decrypt_and_verify(encrypted_message, on_rotation: proc { ... })
513
- crypt.decrypt_and_verify(another_encrypted_message, on_rotation: proc { ... })
1262
+ *John Hawthorn*
514
1263
 
515
- After:
1264
+ * Change the default serializer of `ActiveSupport::MessageVerifier` from
1265
+ `Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
516
1266
 
517
- crypt = ActiveSupport::MessageEncryptor.new('long_secret', on_rotation: proc { ... })
518
- crypt.decrypt_and_verify(encrypted_message)
519
- crypt.decrypt_and_verify(another_encrypted_message)
1267
+ Messages serialized with `Marshal` can still be read, but new messages will
1268
+ be serialized with `ActiveSupport::JSON`. For more information, see
1269
+ https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
520
1270
 
521
- *Edouard Chin*
1271
+ *Saba Kiaei*, *David Buckley*, and *Jonathan Hefner*
522
1272
 
523
- * `delegate_missing_to` would raise a `DelegationError` if the object
524
- delegated to was `nil`. Now the `allow_nil` option has been added to enable
525
- the user to specify they want `nil` returned in this case.
1273
+ * Change the default serializer of `ActiveSupport::MessageEncryptor` from
1274
+ `Marshal` to `ActiveSupport::JSON` when using `config.load_defaults 7.1`.
526
1275
 
527
- *Matthew Tanous*
1276
+ Messages serialized with `Marshal` can still be read, but new messages will
1277
+ be serialized with `ActiveSupport::JSON`. For more information, see
1278
+ https://guides.rubyonrails.org/v7.1/configuring.html#config-active-support-message-serializer.
528
1279
 
529
- * `truncate` would return the original string if it was too short to be truncated
530
- and a frozen string if it were long enough to be truncated. Now truncate will
531
- consistently return an unfrozen string regardless. This behavior is consistent
532
- with `gsub` and `strip`.
1280
+ *Zack Deveau*, *Martin Gingras*, and *Jonathan Hefner*
533
1281
 
534
- Before:
1282
+ * Add `ActiveSupport::TestCase#stub_const` to stub a constant for the duration of a yield.
535
1283
 
536
- 'foobar'.truncate(5).frozen?
537
- # => true
538
- 'foobar'.truncate(6).frozen?
539
- # => false
1284
+ *DHH*
540
1285
 
541
- After:
1286
+ * Fix `ActiveSupport::EncryptedConfiguration` to be compatible with Psych 4
1287
+
1288
+ *Stephen Sugden*
1289
+
1290
+ * Improve `File.atomic_write` error handling
542
1291
 
543
- 'foobar'.truncate(5).frozen?
544
- # => false
545
- 'foobar'.truncate(6).frozen?
546
- # => false
1292
+ *Daniel Pepper*
547
1293
 
548
- *Jordan Thomas*
1294
+ * Fix `Class#descendants` and `DescendantsTracker#descendants` compatibility with Ruby 3.1.
549
1295
 
1296
+ [The native `Class#descendants` was reverted prior to Ruby 3.1 release](https://bugs.ruby-lang.org/issues/14394#note-33),
1297
+ but `Class#subclasses` was kept, breaking the feature detection.
1298
+
1299
+ *Jean Boussier*
550
1300
 
551
- Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activesupport/CHANGELOG.md) for previous changes.
1301
+ Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activesupport/CHANGELOG.md) for previous changes.