activesupport 6.0.3.7 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +220 -533
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_support/actionable_error.rb +1 -1
  6. data/lib/active_support/array_inquirer.rb +2 -2
  7. data/lib/active_support/backtrace_cleaner.rb +3 -3
  8. data/lib/active_support/benchmarkable.rb +3 -3
  9. data/lib/active_support/cache/file_store.rb +18 -11
  10. data/lib/active_support/cache/mem_cache_store.rb +143 -37
  11. data/lib/active_support/cache/memory_store.rb +56 -28
  12. data/lib/active_support/cache/null_store.rb +10 -2
  13. data/lib/active_support/cache/redis_cache_store.rb +63 -88
  14. data/lib/active_support/cache/strategy/local_cache.rb +46 -57
  15. data/lib/active_support/cache.rb +273 -82
  16. data/lib/active_support/callbacks.rb +226 -118
  17. data/lib/active_support/code_generator.rb +65 -0
  18. data/lib/active_support/concern.rb +49 -5
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  20. data/lib/active_support/concurrency/share_lock.rb +2 -2
  21. data/lib/active_support/configurable.rb +9 -6
  22. data/lib/active_support/configuration_file.rb +51 -0
  23. data/lib/active_support/core_ext/array/access.rb +1 -5
  24. data/lib/active_support/core_ext/array/conversions.rb +9 -7
  25. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  27. data/lib/active_support/core_ext/array.rb +1 -0
  28. data/lib/active_support/core_ext/benchmark.rb +2 -2
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  30. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  31. data/lib/active_support/core_ext/class/subclasses.rb +21 -40
  32. data/lib/active_support/core_ext/date/blank.rb +1 -1
  33. data/lib/active_support/core_ext/date/calculations.rb +4 -4
  34. data/lib/active_support/core_ext/date/conversions.rb +5 -4
  35. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  36. data/lib/active_support/core_ext/date.rb +1 -0
  37. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  38. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  39. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  40. data/lib/active_support/core_ext/date_time/conversions.rb +5 -5
  41. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  42. data/lib/active_support/core_ext/date_time.rb +1 -0
  43. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  44. data/lib/active_support/core_ext/enumerable.rb +139 -15
  45. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  46. data/lib/active_support/core_ext/hash/conversions.rb +2 -2
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  48. data/lib/active_support/core_ext/hash/except.rb +1 -1
  49. data/lib/active_support/core_ext/hash/keys.rb +2 -2
  50. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  51. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  52. data/lib/active_support/core_ext/load_error.rb +1 -1
  53. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  54. data/lib/active_support/core_ext/module/attribute_accessors.rb +25 -29
  55. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +26 -13
  56. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  57. data/lib/active_support/core_ext/module/delegation.rb +40 -36
  58. data/lib/active_support/core_ext/module/introspection.rb +1 -25
  59. data/lib/active_support/core_ext/name_error.rb +23 -2
  60. data/lib/active_support/core_ext/numeric/conversions.rb +79 -72
  61. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  62. data/lib/active_support/core_ext/numeric.rb +1 -0
  63. data/lib/active_support/core_ext/object/blank.rb +2 -2
  64. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  65. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  66. data/lib/active_support/core_ext/object/json.rb +42 -26
  67. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  68. data/lib/active_support/core_ext/object/try.rb +20 -20
  69. data/lib/active_support/core_ext/object/with_options.rb +20 -1
  70. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  71. data/lib/active_support/core_ext/pathname.rb +3 -0
  72. data/lib/active_support/core_ext/range/compare_range.rb +6 -25
  73. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  74. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  75. data/lib/active_support/core_ext/range/each.rb +1 -1
  76. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
  77. data/lib/active_support/core_ext/range.rb +1 -1
  78. data/lib/active_support/core_ext/regexp.rb +8 -1
  79. data/lib/active_support/core_ext/string/access.rb +5 -24
  80. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  81. data/lib/active_support/core_ext/string/filters.rb +1 -1
  82. data/lib/active_support/core_ext/string/inflections.rb +39 -5
  83. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  84. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  85. data/lib/active_support/core_ext/string/output_safety.rb +69 -45
  86. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  87. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  88. data/lib/active_support/core_ext/symbol.rb +3 -0
  89. data/lib/active_support/core_ext/time/calculations.rb +26 -6
  90. data/lib/active_support/core_ext/time/conversions.rb +6 -3
  91. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  92. data/lib/active_support/core_ext/time/zones.rb +4 -19
  93. data/lib/active_support/core_ext/time.rb +1 -0
  94. data/lib/active_support/core_ext/uri.rb +3 -23
  95. data/lib/active_support/core_ext.rb +2 -1
  96. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  97. data/lib/active_support/current_attributes.rb +39 -16
  98. data/lib/active_support/dependencies/interlock.rb +10 -18
  99. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  100. data/lib/active_support/dependencies.rb +58 -764
  101. data/lib/active_support/deprecation/behaviors.rb +19 -3
  102. data/lib/active_support/deprecation/disallowed.rb +56 -0
  103. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  104. data/lib/active_support/deprecation/method_wrappers.rb +6 -5
  105. data/lib/active_support/deprecation/proxy_wrappers.rb +4 -4
  106. data/lib/active_support/deprecation/reporting.rb +50 -7
  107. data/lib/active_support/deprecation.rb +6 -1
  108. data/lib/active_support/descendants_tracker.rb +177 -64
  109. data/lib/active_support/digest.rb +5 -3
  110. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  111. data/lib/active_support/duration/iso8601_serializer.rb +24 -10
  112. data/lib/active_support/duration.rb +134 -55
  113. data/lib/active_support/encrypted_configuration.rb +11 -1
  114. data/lib/active_support/encrypted_file.rb +20 -3
  115. data/lib/active_support/environment_inquirer.rb +20 -0
  116. data/lib/active_support/error_reporter.rb +117 -0
  117. data/lib/active_support/evented_file_update_checker.rb +70 -134
  118. data/lib/active_support/execution_context/test_helper.rb +13 -0
  119. data/lib/active_support/execution_context.rb +53 -0
  120. data/lib/active_support/execution_wrapper.rb +30 -4
  121. data/lib/active_support/executor/test_helper.rb +7 -0
  122. data/lib/active_support/fork_tracker.rb +71 -0
  123. data/lib/active_support/gem_version.rb +3 -3
  124. data/lib/active_support/hash_with_indifferent_access.rb +51 -25
  125. data/lib/active_support/html_safe_translation.rb +43 -0
  126. data/lib/active_support/i18n.rb +1 -0
  127. data/lib/active_support/i18n_railtie.rb +14 -19
  128. data/lib/active_support/inflector/inflections.rb +24 -9
  129. data/lib/active_support/inflector/methods.rb +29 -49
  130. data/lib/active_support/inflector/transliterate.rb +4 -4
  131. data/lib/active_support/isolated_execution_state.rb +56 -0
  132. data/lib/active_support/json/decoding.rb +4 -4
  133. data/lib/active_support/json/encoding.rb +8 -4
  134. data/lib/active_support/key_generator.rb +19 -2
  135. data/lib/active_support/locale/en.yml +8 -4
  136. data/lib/active_support/log_subscriber.rb +21 -3
  137. data/lib/active_support/logger.rb +1 -1
  138. data/lib/active_support/logger_silence.rb +2 -26
  139. data/lib/active_support/logger_thread_safe_level.rb +34 -21
  140. data/lib/active_support/message_encryptor.rb +12 -10
  141. data/lib/active_support/message_verifier.rb +50 -18
  142. data/lib/active_support/messages/metadata.rb +11 -3
  143. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  144. data/lib/active_support/messages/rotator.rb +6 -5
  145. data/lib/active_support/multibyte/chars.rb +13 -52
  146. data/lib/active_support/multibyte/unicode.rb +1 -87
  147. data/lib/active_support/multibyte.rb +1 -1
  148. data/lib/active_support/notifications/fanout.rb +110 -69
  149. data/lib/active_support/notifications/instrumenter.rb +37 -29
  150. data/lib/active_support/notifications.rb +47 -26
  151. data/lib/active_support/number_helper/number_converter.rb +2 -4
  152. data/lib/active_support/number_helper/number_to_currency_converter.rb +10 -9
  153. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  154. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  155. data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
  156. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  157. data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
  158. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  159. data/lib/active_support/number_helper.rb +29 -16
  160. data/lib/active_support/option_merger.rb +9 -16
  161. data/lib/active_support/ordered_hash.rb +1 -1
  162. data/lib/active_support/ordered_options.rb +8 -2
  163. data/lib/active_support/parameter_filter.rb +21 -11
  164. data/lib/active_support/per_thread_registry.rb +6 -1
  165. data/lib/active_support/rails.rb +1 -4
  166. data/lib/active_support/railtie.rb +77 -5
  167. data/lib/active_support/rescuable.rb +6 -6
  168. data/lib/active_support/ruby_features.rb +7 -0
  169. data/lib/active_support/secure_compare_rotator.rb +51 -0
  170. data/lib/active_support/security_utils.rb +19 -12
  171. data/lib/active_support/string_inquirer.rb +2 -2
  172. data/lib/active_support/subscriber.rb +19 -25
  173. data/lib/active_support/tagged_logging.rb +31 -6
  174. data/lib/active_support/test_case.rb +9 -21
  175. data/lib/active_support/testing/assertions.rb +49 -12
  176. data/lib/active_support/testing/deprecation.rb +52 -1
  177. data/lib/active_support/testing/isolation.rb +2 -2
  178. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  179. data/lib/active_support/testing/parallelization/server.rb +82 -0
  180. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  181. data/lib/active_support/testing/parallelization.rb +16 -95
  182. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  183. data/lib/active_support/testing/stream.rb +3 -5
  184. data/lib/active_support/testing/tagged_logging.rb +1 -1
  185. data/lib/active_support/testing/time_helpers.rb +53 -5
  186. data/lib/active_support/time_with_zone.rb +120 -55
  187. data/lib/active_support/values/time_zone.rb +49 -18
  188. data/lib/active_support/xml_mini/jdom.rb +1 -1
  189. data/lib/active_support/xml_mini/libxml.rb +5 -5
  190. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  191. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  192. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  193. data/lib/active_support/xml_mini/rexml.rb +9 -2
  194. data/lib/active_support/xml_mini.rb +5 -4
  195. data/lib/active_support.rb +29 -1
  196. metadata +46 -45
  197. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  198. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  199. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  200. data/lib/active_support/core_ext/marshal.rb +0 -24
  201. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  202. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  203. data/lib/active_support/core_ext/range/include_range.rb +0 -9
  204. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -30,6 +30,8 @@ class String
30
30
  # 'apple'.pluralize(2) # => "apples"
31
31
  # 'ley'.pluralize(:es) # => "leyes"
32
32
  # 'ley'.pluralize(1, :es) # => "ley"
33
+ #
34
+ # See ActiveSupport::Inflector.pluralize.
33
35
  def pluralize(count = nil, locale = :en)
34
36
  locale = count if count.is_a?(Symbol)
35
37
  if count == 1
@@ -53,28 +55,34 @@ class String
53
55
  # 'the blue mailmen'.singularize # => "the blue mailman"
54
56
  # 'CamelOctopi'.singularize # => "CamelOctopus"
55
57
  # 'leyes'.singularize(:es) # => "ley"
58
+ #
59
+ # See ActiveSupport::Inflector.singularize.
56
60
  def singularize(locale = :en)
57
61
  ActiveSupport::Inflector.singularize(self, locale)
58
62
  end
59
63
 
60
64
  # +constantize+ tries to find a declared constant with the name specified
61
65
  # in the string. It raises a NameError when the name is not in CamelCase
62
- # or is not initialized. See ActiveSupport::Inflector.constantize
66
+ # or is not initialized.
63
67
  #
64
68
  # 'Module'.constantize # => Module
65
69
  # 'Class'.constantize # => Class
66
70
  # 'blargle'.constantize # => NameError: wrong constant name blargle
71
+ #
72
+ # See ActiveSupport::Inflector.constantize.
67
73
  def constantize
68
74
  ActiveSupport::Inflector.constantize(self)
69
75
  end
70
76
 
71
77
  # +safe_constantize+ tries to find a declared constant with the name specified
72
78
  # in the string. It returns +nil+ when the name is not in CamelCase
73
- # or is not initialized. See ActiveSupport::Inflector.safe_constantize
79
+ # or is not initialized.
74
80
  #
75
81
  # 'Module'.safe_constantize # => Module
76
82
  # 'Class'.safe_constantize # => Class
77
83
  # 'blargle'.safe_constantize # => nil
84
+ #
85
+ # See ActiveSupport::Inflector.safe_constantize.
78
86
  def safe_constantize
79
87
  ActiveSupport::Inflector.safe_constantize(self)
80
88
  end
@@ -88,6 +96,10 @@ class String
88
96
  # 'active_record'.camelize(:lower) # => "activeRecord"
89
97
  # 'active_record/errors'.camelize # => "ActiveRecord::Errors"
90
98
  # 'active_record/errors'.camelize(:lower) # => "activeRecord::Errors"
99
+ #
100
+ # +camelize+ is also aliased as +camelcase+.
101
+ #
102
+ # See ActiveSupport::Inflector.camelize.
91
103
  def camelize(first_letter = :upper)
92
104
  case first_letter
93
105
  when :upper
@@ -108,11 +120,13 @@ class String
108
120
  # optional parameter +keep_id_suffix+ to true.
109
121
  # By default, this parameter is false.
110
122
  #
111
- # +titleize+ is also aliased as +titlecase+.
112
- #
113
123
  # 'man from the boondocks'.titleize # => "Man From The Boondocks"
114
124
  # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
115
125
  # 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
126
+ #
127
+ # +titleize+ is also aliased as +titlecase+.
128
+ #
129
+ # See ActiveSupport::Inflector.titleize.
116
130
  def titleize(keep_id_suffix: false)
117
131
  ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
118
132
  end
@@ -124,6 +138,8 @@ class String
124
138
  #
125
139
  # 'ActiveModel'.underscore # => "active_model"
126
140
  # 'ActiveModel::Errors'.underscore # => "active_model/errors"
141
+ #
142
+ # See ActiveSupport::Inflector.underscore.
127
143
  def underscore
128
144
  ActiveSupport::Inflector.underscore(self)
129
145
  end
@@ -131,6 +147,8 @@ class String
131
147
  # Replaces underscores with dashes in the string.
132
148
  #
133
149
  # 'puni_puni'.dasherize # => "puni-puni"
150
+ #
151
+ # See ActiveSupport::Inflector.dasherize.
134
152
  def dasherize
135
153
  ActiveSupport::Inflector.dasherize(self)
136
154
  end
@@ -142,6 +160,8 @@ class String
142
160
  # '::Inflections'.demodulize # => "Inflections"
143
161
  # ''.demodulize # => ''
144
162
  #
163
+ # See ActiveSupport::Inflector.demodulize.
164
+ #
145
165
  # See also +deconstantize+.
146
166
  def demodulize
147
167
  ActiveSupport::Inflector.demodulize(self)
@@ -155,6 +175,8 @@ class String
155
175
  # '::String'.deconstantize # => ""
156
176
  # ''.deconstantize # => ""
157
177
  #
178
+ # See ActiveSupport::Inflector.deconstantize.
179
+ #
158
180
  # See also +demodulize+.
159
181
  def deconstantize
160
182
  ActiveSupport::Inflector.deconstantize(self)
@@ -192,6 +214,8 @@ class String
192
214
  #
193
215
  # <%= link_to(@person.name, person_path) %>
194
216
  # # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
217
+ #
218
+ # See ActiveSupport::Inflector.parameterize.
195
219
  def parameterize(separator: "-", preserve_case: false, locale: nil)
196
220
  ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case, locale: locale)
197
221
  end
@@ -202,6 +226,8 @@ class String
202
226
  # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
203
227
  # 'ham_and_egg'.tableize # => "ham_and_eggs"
204
228
  # 'fancyCategory'.tableize # => "fancy_categories"
229
+ #
230
+ # See ActiveSupport::Inflector.tableize.
205
231
  def tableize
206
232
  ActiveSupport::Inflector.tableize(self)
207
233
  end
@@ -212,6 +238,8 @@ class String
212
238
  #
213
239
  # 'ham_and_eggs'.classify # => "HamAndEgg"
214
240
  # 'posts'.classify # => "Post"
241
+ #
242
+ # See ActiveSupport::Inflector.classify.
215
243
  def classify
216
244
  ActiveSupport::Inflector.classify(self)
217
245
  end
@@ -232,7 +260,9 @@ class String
232
260
  # 'author_id'.humanize # => "Author"
233
261
  # 'author_id'.humanize(capitalize: false) # => "author"
234
262
  # '_id'.humanize # => "Id"
235
- # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
263
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author id"
264
+ #
265
+ # See ActiveSupport::Inflector.humanize.
236
266
  def humanize(capitalize: true, keep_id_suffix: false)
237
267
  ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
238
268
  end
@@ -242,6 +272,8 @@ class String
242
272
  # 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
243
273
  # 'w'.upcase_first # => "W"
244
274
  # ''.upcase_first # => ""
275
+ #
276
+ # See ActiveSupport::Inflector.upcase_first.
245
277
  def upcase_first
246
278
  ActiveSupport::Inflector.upcase_first(self)
247
279
  end
@@ -253,6 +285,8 @@ class String
253
285
  # 'Message'.foreign_key # => "message_id"
254
286
  # 'Message'.foreign_key(false) # => "messageid"
255
287
  # 'Admin::Post'.foreign_key # => "post_id"
288
+ #
289
+ # See ActiveSupport::Inflector.foreign_key.
256
290
  def foreign_key(separate_class_name_and_id_with_underscore = true)
257
291
  ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
258
292
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/string_inquirer"
4
+ require "active_support/environment_inquirer"
4
5
 
5
6
  class String
6
7
  # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
@@ -47,9 +47,9 @@ class String
47
47
  # iso_str.is_utf8? # => false
48
48
  def is_utf8?
49
49
  case encoding
50
- when Encoding::UTF_8
50
+ when Encoding::UTF_8, Encoding::US_ASCII
51
51
  valid_encoding?
52
- when Encoding::ASCII_8BIT, Encoding::US_ASCII
52
+ when Encoding::ASCII_8BIT
53
53
  dup.force_encoding(Encoding::UTF_8).valid_encoding?
54
54
  else
55
55
  false
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "erb"
4
- require "active_support/core_ext/kernel/singleton_class"
5
4
  require "active_support/core_ext/module/redefine_method"
6
5
  require "active_support/multibyte/unicode"
7
6
 
@@ -85,7 +84,7 @@ class ERB
85
84
  # use inside HTML attributes.
86
85
  #
87
86
  # If your JSON is being used downstream for insertion into the DOM, be aware of
88
- # whether or not it is being inserted via +html()+. Most jQuery plugins do this.
87
+ # whether or not it is being inserted via <tt>html()</tt>. Most jQuery plugins do this.
89
88
  # If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
90
89
  # content returned by your JSON.
91
90
  #
@@ -131,11 +130,11 @@ class Numeric
131
130
  end
132
131
  end
133
132
 
134
- module ActiveSupport #:nodoc:
133
+ module ActiveSupport # :nodoc:
135
134
  class SafeBuffer < String
136
135
  UNSAFE_STRING_METHODS = %w(
137
136
  capitalize chomp chop delete delete_prefix delete_suffix
138
- downcase lstrip next reverse rstrip slice squeeze strip
137
+ downcase lstrip next reverse rstrip scrub slice squeeze strip
139
138
  succ swapcase tr tr_s unicode_normalize upcase
140
139
  )
141
140
 
@@ -153,12 +152,12 @@ module ActiveSupport #:nodoc:
153
152
 
154
153
  def [](*args)
155
154
  if html_safe?
156
- new_safe_buffer = super
155
+ new_string = super
157
156
 
158
- if new_safe_buffer
159
- new_safe_buffer.instance_variable_set :@html_safe, true
160
- end
157
+ return unless new_string
161
158
 
159
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
160
+ new_safe_buffer.instance_variable_set :@html_safe, true
162
161
  new_safe_buffer
163
162
  else
164
163
  to_str[*args]
@@ -185,27 +184,30 @@ module ActiveSupport #:nodoc:
185
184
  end
186
185
 
187
186
  def concat(value)
188
- super(html_escape_interpolated_argument(value))
187
+ unless value.nil?
188
+ super(implicit_html_escape_interpolated_argument(value))
189
+ end
190
+ self
189
191
  end
190
192
  alias << concat
191
193
 
192
194
  def insert(index, value)
193
- super(index, html_escape_interpolated_argument(value))
195
+ super(index, implicit_html_escape_interpolated_argument(value))
194
196
  end
195
197
 
196
198
  def prepend(value)
197
- super(html_escape_interpolated_argument(value))
199
+ super(implicit_html_escape_interpolated_argument(value))
198
200
  end
199
201
 
200
202
  def replace(value)
201
- super(html_escape_interpolated_argument(value))
203
+ super(implicit_html_escape_interpolated_argument(value))
202
204
  end
203
205
 
204
206
  def []=(*args)
205
- if args.count == 3
206
- super(args[0], args[1], html_escape_interpolated_argument(args[2]))
207
+ if args.length == 3
208
+ super(args[0], args[1], implicit_html_escape_interpolated_argument(args[2]))
207
209
  else
208
- super(args[0], html_escape_interpolated_argument(args[1]))
210
+ super(args[0], implicit_html_escape_interpolated_argument(args[1]))
209
211
  end
210
212
  end
211
213
 
@@ -214,7 +216,8 @@ module ActiveSupport #:nodoc:
214
216
  end
215
217
 
216
218
  def *(*)
217
- new_safe_buffer = super
219
+ new_string = super
220
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
218
221
  new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
219
222
  new_safe_buffer
220
223
  end
@@ -222,9 +225,9 @@ module ActiveSupport #:nodoc:
222
225
  def %(args)
223
226
  case args
224
227
  when Hash
225
- escaped_args = Hash[args.map { |k, arg| [k, html_escape_interpolated_argument(arg)] }]
228
+ escaped_args = args.transform_values { |arg| explicit_html_escape_interpolated_argument(arg) }
226
229
  else
227
- escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
230
+ escaped_args = Array(args).map { |arg| explicit_html_escape_interpolated_argument(arg) }
228
231
  end
229
232
 
230
233
  self.class.new(super(escaped_args))
@@ -262,39 +265,60 @@ module ActiveSupport #:nodoc:
262
265
  end
263
266
 
264
267
  UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
265
- if unsafe_method.respond_to?(unsafe_method)
266
- class_eval <<-EOT, __FILE__, __LINE__ + 1
267
- def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
268
- if block # if block
269
- to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
270
- set_block_back_references(block, $~) # set_block_back_references(block, $~)
271
- block.call(*params) # block.call(*params)
272
- } # }
273
- else # else
274
- to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
275
- end # end
276
- end # end
277
-
278
- def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
279
- @html_safe = false # @html_safe = false
280
- if block # if block
281
- super(*args) { |*params| # super(*args) { |*params|
282
- set_block_back_references(block, $~) # set_block_back_references(block, $~)
283
- block.call(*params) # block.call(*params)
284
- } # }
285
- else # else
286
- super # super
287
- end # end
288
- end # end
289
- EOT
290
- end
268
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
269
+ def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
270
+ if block # if block
271
+ to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
272
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
273
+ block.call(*params) # block.call(*params)
274
+ } # }
275
+ else # else
276
+ to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
277
+ end # end
278
+ end # end
279
+
280
+ def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
281
+ @html_safe = false # @html_safe = false
282
+ if block # if block
283
+ super(*args) { |*params| # super(*args) { |*params|
284
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
285
+ block.call(*params) # block.call(*params)
286
+ } # }
287
+ else # else
288
+ super # super
289
+ end # end
290
+ end # end
291
+ EOT
291
292
  end
292
293
 
293
294
  private
294
- def html_escape_interpolated_argument(arg)
295
+ def explicit_html_escape_interpolated_argument(arg)
295
296
  (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
296
297
  end
297
298
 
299
+ def implicit_html_escape_interpolated_argument(arg)
300
+ if !html_safe? || arg.html_safe?
301
+ arg
302
+ else
303
+ arg_string = begin
304
+ arg.to_str
305
+ rescue NoMethodError => error
306
+ if error.name == :to_str
307
+ str = arg.to_s
308
+ ActiveSupport::Deprecation.warn <<~MSG.squish
309
+ Implicit conversion of #{arg.class} into String by ActiveSupport::SafeBuffer
310
+ is deprecated and will be removed in Rails 7.1.
311
+ You must explicitly cast it to a String.
312
+ MSG
313
+ str
314
+ else
315
+ raise
316
+ end
317
+ end
318
+ CGI.escapeHTML(arg_string)
319
+ end
320
+ end
321
+
298
322
  def set_block_back_references(block, match_data)
299
323
  block.binding.eval("proc { |m| $~ = m }").call(match_data)
300
324
  rescue ArgumentError
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class String
4
- alias_method :starts_with?, :start_with?
5
- alias_method :ends_with?, :end_with?
4
+ alias :starts_with? :start_with?
5
+ alias :ends_with? :end_with?
6
6
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Symbol
4
+ alias :starts_with? :start_with?
5
+ alias :ends_with? :end_with?
6
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/symbol/starts_ends_with"
@@ -6,6 +6,7 @@ require "active_support/time_with_zone"
6
6
  require "active_support/core_ext/time/zones"
7
7
  require "active_support/core_ext/date_and_time/calculations"
8
8
  require "active_support/core_ext/date/calculations"
9
+ require "active_support/core_ext/module/remove_method"
9
10
 
10
11
  class Time
11
12
  include DateAndTime::Calculations
@@ -41,13 +42,15 @@ class Time
41
42
 
42
43
  # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
43
44
  # instances can be used when called with a single argument
44
- def at_with_coercion(*args)
45
- return at_without_coercion(*args) if args.size != 1
45
+ def at_with_coercion(*args, **kwargs)
46
+ return at_without_coercion(*args, **kwargs) if args.size != 1 || !kwargs.empty?
46
47
 
47
48
  # Time.at can be called with a time or numerical value
48
49
  time_or_number = args.first
49
50
 
50
- if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime)
51
+ if time_or_number.is_a?(ActiveSupport::TimeWithZone)
52
+ at_without_coercion(time_or_number.to_r).getlocal
53
+ elsif time_or_number.is_a?(DateTime)
51
54
  at_without_coercion(time_or_number.to_f).getlocal
52
55
  else
53
56
  at_without_coercion(time_or_number)
@@ -105,6 +108,21 @@ class Time
105
108
  subsec
106
109
  end
107
110
 
111
+ unless Time.method_defined?(:floor)
112
+ def floor(precision = 0)
113
+ change(nsec: 0) + subsec.floor(precision)
114
+ end
115
+ end
116
+
117
+ # Restricted Ruby version due to a bug in `Time#ceil`
118
+ # See https://bugs.ruby-lang.org/issues/17025 for more details
119
+ if RUBY_VERSION <= "2.8"
120
+ remove_possible_method :ceil
121
+ def ceil(precision = 0)
122
+ change(nsec: 0) + subsec.ceil(precision)
123
+ end
124
+ end
125
+
108
126
  # Returns a new Time where one or more of the elements have been changed according
109
127
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
110
128
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
@@ -141,6 +159,8 @@ class Time
141
159
  ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
142
160
  elsif utc?
143
161
  ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
162
+ elsif zone&.respond_to?(:utc_to_local)
163
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
144
164
  elsif zone
145
165
  ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
146
166
  else
@@ -257,7 +277,7 @@ class Time
257
277
  end
258
278
  alias :at_end_of_minute :end_of_minute
259
279
 
260
- def plus_with_duration(other) #:nodoc:
280
+ def plus_with_duration(other) # :nodoc:
261
281
  if ActiveSupport::Duration === other
262
282
  other.since(self)
263
283
  else
@@ -267,7 +287,7 @@ class Time
267
287
  alias_method :plus_without_duration, :+
268
288
  alias_method :+, :plus_with_duration
269
289
 
270
- def minus_with_duration(other) #:nodoc:
290
+ def minus_with_duration(other) # :nodoc:
271
291
  if ActiveSupport::Duration === other
272
292
  other.until(self)
273
293
  else
@@ -285,7 +305,7 @@ class Time
285
305
  other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
286
306
  end
287
307
  alias_method :minus_without_coercion, :-
288
- alias_method :-, :minus_with_coercion
308
+ alias_method :-, :minus_with_coercion # rubocop:disable Lint/DuplicateMethods
289
309
 
290
310
  # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
291
311
  # can be chronologically compared with a Time
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "time"
3
4
  require "active_support/inflector/methods"
4
5
  require "active_support/values/time_zone"
5
6
 
6
7
  class Time
7
8
  DATE_FORMATS = {
8
9
  db: "%Y-%m-%d %H:%M:%S",
10
+ inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
9
11
  number: "%Y%m%d%H%M%S",
10
12
  nsec: "%Y%m%d%H%M%S%9N",
11
13
  usec: "%Y%m%d%H%M%S%6N",
@@ -25,12 +27,12 @@ class Time
25
27
 
26
28
  # Converts to a formatted string. See DATE_FORMATS for built-in formats.
27
29
  #
28
- # This method is aliased to <tt>to_s</tt>.
30
+ # This method is aliased to <tt>to_fs</tt>.
29
31
  #
30
32
  # time = Time.now # => 2007-01-18 06:10:17 -06:00
31
33
  #
32
34
  # time.to_formatted_s(:time) # => "06:10"
33
- # time.to_s(:time) # => "06:10"
35
+ # time.to_fs(:time) # => "06:10"
34
36
  #
35
37
  # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
36
38
  # time.to_formatted_s(:number) # => "20070118061017"
@@ -52,11 +54,12 @@ class Time
52
54
  if formatter = DATE_FORMATS[format]
53
55
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
54
56
  else
57
+ # Change to `to_s` when deprecation is gone. Also deprecate `to_default_s`.
55
58
  to_default_s
56
59
  end
57
60
  end
61
+ alias_method :to_fs, :to_formatted_s
58
62
  alias_method :to_default_s, :to_s
59
- alias_method :to_s, :to_formatted_s
60
63
 
61
64
  # Returns a formatted string of the offset from UTC, or an alternative
62
65
  # string if the time zone is already UTC.
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ class Time
6
+ NOT_SET = Object.new # :nodoc:
7
+ def to_s(format = NOT_SET) # :nodoc:
8
+ if formatter = DATE_FORMATS[format]
9
+ ActiveSupport::Deprecation.warn(
10
+ "Time#to_s(#{format.inspect}) is deprecated. Please use Time#to_formatted_s(#{format.inspect}) instead."
11
+ )
12
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
13
+ elsif format == NOT_SET
14
+ to_default_s
15
+ else
16
+ ActiveSupport::Deprecation.warn(
17
+ "Time#to_s(#{format.inspect}) is deprecated. Please use Time#to_formatted_s(#{format.inspect}) instead."
18
+ )
19
+ to_default_s
20
+ end
21
+ end
22
+ end
@@ -12,7 +12,7 @@ class Time
12
12
  # Returns the TimeZone for the current request, if this has been set (via Time.zone=).
13
13
  # If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
14
14
  def zone
15
- Thread.current[:time_zone] || zone_default
15
+ ::ActiveSupport::IsolatedExecutionState[:time_zone] || zone_default
16
16
  end
17
17
 
18
18
  # Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
@@ -39,7 +39,7 @@ class Time
39
39
  # end
40
40
  # end
41
41
  def zone=(time_zone)
42
- Thread.current[:time_zone] = find_zone!(time_zone)
42
+ ::ActiveSupport::IsolatedExecutionState[:time_zone] = find_zone!(time_zone)
43
43
  end
44
44
 
45
45
  # Allows override of <tt>Time.zone</tt> locally inside supplied block;
@@ -80,24 +80,9 @@ class Time
80
80
  # Time.find_zone! false # => false
81
81
  # Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
82
82
  def find_zone!(time_zone)
83
- if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
84
- time_zone
85
- else
86
- # Look up the timezone based on the identifier (unless we've been
87
- # passed a TZInfo::Timezone)
88
- unless time_zone.respond_to?(:period_for_local)
89
- time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
90
- end
83
+ return time_zone unless time_zone
91
84
 
92
- # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
93
- if time_zone.is_a?(ActiveSupport::TimeZone)
94
- time_zone
95
- else
96
- ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
97
- end
98
- end
99
- rescue TZInfo::InvalidTimezoneIdentifier
100
- raise ArgumentError, "Invalid Timezone: #{time_zone}"
85
+ ActiveSupport::TimeZone[time_zone] || raise(ArgumentError, "Invalid Timezone: #{time_zone}")
101
86
  end
102
87
 
103
88
  # Returns a TimeZone instance matching the time zone provided.
@@ -4,4 +4,5 @@ require "active_support/core_ext/time/acts_like"
4
4
  require "active_support/core_ext/time/calculations"
5
5
  require "active_support/core_ext/time/compatibility"
6
6
  require "active_support/core_ext/time/conversions"
7
+ require "active_support/core_ext/time/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
7
8
  require "active_support/core_ext/time/zones"
@@ -1,25 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "uri"
4
-
5
- if RUBY_VERSION < "2.6.0"
6
- require "active_support/core_ext/module/redefine_method"
7
- URI::Parser.class_eval do
8
- silence_redefinition_of_method :unescape
9
- def unescape(str, escaped = /%[a-fA-F\d]{2}/)
10
- # TODO: Are we actually sure that ASCII == UTF-8?
11
- # YK: My initial experiments say yes, but let's be sure please
12
- enc = str.encoding
13
- enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
14
- str.dup.force_encoding(Encoding::ASCII_8BIT).gsub(escaped) { |match| [match[1, 2].hex].pack("C") }.force_encoding(enc)
15
- end
16
- end
17
- end
18
-
19
- module URI
20
- class << self
21
- def parser
22
- @parser ||= URI::Parser.new
23
- end
24
- end
25
- end
3
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
4
+ `active_support/core_ext/uri` is deprecated and will be removed in Rails 7.1.
5
+ MSG
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).each do |path|
3
+ Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).sort.each do |path|
4
+ next if path.end_with?("core_ext/uri.rb")
4
5
  require path
5
6
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport::CurrentAttributes::TestHelper # :nodoc:
4
+ def before_setup
5
+ ActiveSupport::CurrentAttributes.reset_all
6
+ super
7
+ end
8
+
9
+ def after_teardown
10
+ super
11
+ ActiveSupport::CurrentAttributes.reset_all
12
+ end
13
+ end