activesupport 6.1.6.1 → 7.0.3.1

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 (179) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +231 -515
  3. data/lib/active_support/actionable_error.rb +1 -1
  4. data/lib/active_support/array_inquirer.rb +0 -2
  5. data/lib/active_support/backtrace_cleaner.rb +2 -2
  6. data/lib/active_support/benchmarkable.rb +2 -2
  7. data/lib/active_support/cache/file_store.rb +15 -9
  8. data/lib/active_support/cache/mem_cache_store.rb +132 -37
  9. data/lib/active_support/cache/memory_store.rb +24 -16
  10. data/lib/active_support/cache/null_store.rb +10 -2
  11. data/lib/active_support/cache/redis_cache_store.rb +47 -72
  12. data/lib/active_support/cache/strategy/local_cache.rb +38 -61
  13. data/lib/active_support/cache.rb +193 -46
  14. data/lib/active_support/callbacks.rb +184 -85
  15. data/lib/active_support/code_generator.rb +65 -0
  16. data/lib/active_support/concern.rb +5 -5
  17. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  18. data/lib/active_support/concurrency/share_lock.rb +2 -2
  19. data/lib/active_support/configurable.rb +8 -5
  20. data/lib/active_support/configuration_file.rb +1 -1
  21. data/lib/active_support/core_ext/array/access.rb +1 -5
  22. data/lib/active_support/core_ext/array/conversions.rb +13 -12
  23. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  24. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  25. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  26. data/lib/active_support/core_ext/array.rb +1 -0
  27. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  28. data/lib/active_support/core_ext/class/subclasses.rb +25 -17
  29. data/lib/active_support/core_ext/date/blank.rb +1 -1
  30. data/lib/active_support/core_ext/date/calculations.rb +9 -9
  31. data/lib/active_support/core_ext/date/conversions.rb +14 -14
  32. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  33. data/lib/active_support/core_ext/date.rb +1 -0
  34. data/lib/active_support/core_ext/date_and_time/calculations.rb +4 -4
  35. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  36. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  37. data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
  38. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  39. data/lib/active_support/core_ext/date_time.rb +1 -0
  40. data/lib/active_support/core_ext/digest/uuid.rb +39 -14
  41. data/lib/active_support/core_ext/enumerable.rb +101 -32
  42. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  43. data/lib/active_support/core_ext/hash/conversions.rb +0 -1
  44. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  45. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  46. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  47. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  48. data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -0
  49. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +19 -10
  50. data/lib/active_support/core_ext/module/delegation.rb +2 -8
  51. data/lib/active_support/core_ext/name_error.rb +2 -8
  52. data/lib/active_support/core_ext/numeric/conversions.rb +80 -77
  53. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  54. data/lib/active_support/core_ext/numeric.rb +1 -0
  55. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  56. data/lib/active_support/core_ext/object/blank.rb +2 -2
  57. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  58. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  59. data/lib/active_support/core_ext/object/json.rb +30 -25
  60. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  61. data/lib/active_support/core_ext/object/try.rb +20 -20
  62. data/lib/active_support/core_ext/object/with_options.rb +20 -1
  63. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  64. data/lib/active_support/core_ext/pathname.rb +3 -0
  65. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  66. data/lib/active_support/core_ext/range/conversions.rb +8 -8
  67. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  68. data/lib/active_support/core_ext/range/each.rb +1 -1
  69. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -25
  70. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  71. data/lib/active_support/core_ext/range.rb +1 -1
  72. data/lib/active_support/core_ext/securerandom.rb +1 -1
  73. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  74. data/lib/active_support/core_ext/string/filters.rb +1 -1
  75. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  76. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  77. data/lib/active_support/core_ext/string/output_safety.rb +62 -38
  78. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  79. data/lib/active_support/core_ext/time/calculations.rb +7 -8
  80. data/lib/active_support/core_ext/time/conversions.rb +13 -12
  81. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  82. data/lib/active_support/core_ext/time/zones.rb +7 -22
  83. data/lib/active_support/core_ext/time.rb +1 -0
  84. data/lib/active_support/core_ext/uri.rb +3 -27
  85. data/lib/active_support/core_ext.rb +1 -0
  86. data/lib/active_support/current_attributes.rb +31 -14
  87. data/lib/active_support/dependencies/interlock.rb +10 -18
  88. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  89. data/lib/active_support/dependencies.rb +58 -788
  90. data/lib/active_support/deprecation/behaviors.rb +5 -2
  91. data/lib/active_support/deprecation/method_wrappers.rb +3 -3
  92. data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
  93. data/lib/active_support/deprecation.rb +2 -2
  94. data/lib/active_support/descendants_tracker.rb +174 -68
  95. data/lib/active_support/digest.rb +4 -4
  96. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  97. data/lib/active_support/duration/iso8601_serializer.rb +9 -1
  98. data/lib/active_support/duration.rb +77 -48
  99. data/lib/active_support/encrypted_configuration.rb +13 -2
  100. data/lib/active_support/encrypted_file.rb +1 -1
  101. data/lib/active_support/environment_inquirer.rb +1 -1
  102. data/lib/active_support/error_reporter.rb +117 -0
  103. data/lib/active_support/evented_file_update_checker.rb +3 -5
  104. data/lib/active_support/execution_context/test_helper.rb +13 -0
  105. data/lib/active_support/execution_context.rb +53 -0
  106. data/lib/active_support/execution_wrapper.rb +30 -11
  107. data/lib/active_support/executor/test_helper.rb +7 -0
  108. data/lib/active_support/fork_tracker.rb +19 -12
  109. data/lib/active_support/gem_version.rb +4 -4
  110. data/lib/active_support/hash_with_indifferent_access.rb +3 -1
  111. data/lib/active_support/html_safe_translation.rb +43 -0
  112. data/lib/active_support/i18n.rb +1 -0
  113. data/lib/active_support/i18n_railtie.rb +1 -1
  114. data/lib/active_support/inflector/inflections.rb +23 -7
  115. data/lib/active_support/inflector/methods.rb +24 -48
  116. data/lib/active_support/inflector/transliterate.rb +1 -1
  117. data/lib/active_support/isolated_execution_state.rb +72 -0
  118. data/lib/active_support/json/encoding.rb +3 -3
  119. data/lib/active_support/key_generator.rb +22 -5
  120. data/lib/active_support/lazy_load_hooks.rb +14 -3
  121. data/lib/active_support/locale/en.yml +1 -1
  122. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  123. data/lib/active_support/log_subscriber.rb +15 -5
  124. data/lib/active_support/logger.rb +4 -5
  125. data/lib/active_support/logger_thread_safe_level.rb +4 -13
  126. data/lib/active_support/message_encryptor.rb +12 -6
  127. data/lib/active_support/message_verifier.rb +46 -14
  128. data/lib/active_support/messages/metadata.rb +2 -2
  129. data/lib/active_support/multibyte/chars.rb +10 -11
  130. data/lib/active_support/multibyte/unicode.rb +0 -12
  131. data/lib/active_support/multibyte.rb +1 -1
  132. data/lib/active_support/notifications/fanout.rb +91 -65
  133. data/lib/active_support/notifications/instrumenter.rb +32 -15
  134. data/lib/active_support/notifications.rb +17 -23
  135. data/lib/active_support/number_helper/number_converter.rb +1 -3
  136. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  137. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  138. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  139. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  140. data/lib/active_support/number_helper/rounding_helper.rb +1 -5
  141. data/lib/active_support/number_helper.rb +0 -2
  142. data/lib/active_support/option_merger.rb +8 -16
  143. data/lib/active_support/ordered_hash.rb +1 -1
  144. data/lib/active_support/ordered_options.rb +1 -1
  145. data/lib/active_support/parameter_filter.rb +5 -0
  146. data/lib/active_support/per_thread_registry.rb +5 -1
  147. data/lib/active_support/railtie.rb +69 -19
  148. data/lib/active_support/rescuable.rb +4 -4
  149. data/lib/active_support/ruby_features.rb +7 -0
  150. data/lib/active_support/secure_compare_rotator.rb +2 -2
  151. data/lib/active_support/string_inquirer.rb +0 -2
  152. data/lib/active_support/subscriber.rb +7 -18
  153. data/lib/active_support/tagged_logging.rb +16 -1
  154. data/lib/active_support/test_case.rb +9 -21
  155. data/lib/active_support/testing/assertions.rb +35 -5
  156. data/lib/active_support/testing/deprecation.rb +52 -1
  157. data/lib/active_support/testing/isolation.rb +2 -2
  158. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  159. data/lib/active_support/testing/parallelization/server.rb +4 -0
  160. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  161. data/lib/active_support/testing/parallelization.rb +4 -0
  162. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  163. data/lib/active_support/testing/stream.rb +3 -5
  164. data/lib/active_support/testing/tagged_logging.rb +1 -1
  165. data/lib/active_support/testing/time_helpers.rb +13 -2
  166. data/lib/active_support/time_with_zone.rb +58 -17
  167. data/lib/active_support/values/time_zone.rb +33 -14
  168. data/lib/active_support/version.rb +1 -1
  169. data/lib/active_support/xml_mini/jdom.rb +1 -1
  170. data/lib/active_support/xml_mini/libxml.rb +5 -5
  171. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  172. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  173. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  174. data/lib/active_support/xml_mini/rexml.rb +1 -1
  175. data/lib/active_support/xml_mini.rb +5 -4
  176. data/lib/active_support.rb +16 -0
  177. metadata +23 -21
  178. data/lib/active_support/core_ext/marshal.rb +0 -26
  179. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/range/conversions"
4
+ require "active_support/core_ext/range/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
4
5
  require "active_support/core_ext/range/compare_range"
5
- require "active_support/core_ext/range/include_time_with_zone"
6
6
  require "active_support/core_ext/range/overlaps"
7
7
  require "active_support/core_ext/range/each"
@@ -12,7 +12,7 @@ module SecureRandom
12
12
  #
13
13
  # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
14
14
  #
15
- # The result may contain alphanumeric characters except 0, O, I and l.
15
+ # The result may contain alphanumeric characters except 0, O, I, and l.
16
16
  #
17
17
  # p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
18
18
  # p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
@@ -5,10 +5,10 @@ require "active_support/core_ext/time/calculations"
5
5
 
6
6
  class String
7
7
  # Converts a string to a Time value.
8
- # The +form+ can be either :utc or :local (default :local).
8
+ # The +form+ can be either +:utc+ or +:local+ (default +:local+).
9
9
  #
10
10
  # The time is parsed using Time.parse method.
11
- # If +form+ is :local, then the time is in the system timezone.
11
+ # If +form+ is +:local+, then the time is in the system timezone.
12
12
  # If the date part is missing then the current date is used and if
13
13
  # the time part is missing then it is assumed to be 00:00:00.
14
14
  #
@@ -106,7 +106,7 @@ class String
106
106
  self.class.new.tap do |cut|
107
107
  cut_at = truncate_at - omission.bytesize
108
108
 
109
- scan(/\X/) do |grapheme|
109
+ each_grapheme_cluster do |grapheme|
110
110
  if cut.bytesize + grapheme.bytesize <= cut_at
111
111
  cut << grapheme
112
112
  else
@@ -260,7 +260,7 @@ class String
260
260
  # 'author_id'.humanize # => "Author"
261
261
  # 'author_id'.humanize(capitalize: false) # => "author"
262
262
  # '_id'.humanize # => "Id"
263
- # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
263
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author id"
264
264
  #
265
265
  # See ActiveSupport::Inflector.humanize.
266
266
  def humanize(capitalize: true, keep_id_suffix: false)
@@ -4,7 +4,7 @@ require "active_support/string_inquirer"
4
4
  require "active_support/environment_inquirer"
5
5
 
6
6
  class String
7
- # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
7
+ # Wraps the current string in the ActiveSupport::StringInquirer class,
8
8
  # which gives you a prettier way to test for equality.
9
9
  #
10
10
  # env = 'production'.inquiry
@@ -105,7 +105,7 @@ class ERB
105
105
  # WARNING: this helper only works with valid JSON. Using this on non-JSON values
106
106
  # will open up serious XSS vulnerabilities. For example, if you replace the
107
107
  # +current_user.to_json+ in the example above with user input instead, the browser
108
- # will happily eval() that string as JavaScript.
108
+ # will happily <tt>eval()</tt> that string as JavaScript.
109
109
  #
110
110
  # The escaping performed in this method is identical to those performed in the
111
111
  # Active Support JSON encoder when +ActiveSupport.escape_html_entities_in_json+ is
@@ -158,7 +158,7 @@ class Numeric
158
158
  end
159
159
  end
160
160
 
161
- module ActiveSupport #:nodoc:
161
+ module ActiveSupport # :nodoc:
162
162
  class SafeBuffer < String
163
163
  UNSAFE_STRING_METHODS = %w(
164
164
  capitalize chomp chop delete delete_prefix delete_suffix
@@ -171,7 +171,7 @@ module ActiveSupport #:nodoc:
171
171
  alias_method :original_concat, :concat
172
172
  private :original_concat
173
173
 
174
- # Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
174
+ # Raised when ActiveSupport::SafeBuffer#safe_concat is called on unsafe buffers.
175
175
  class SafeConcatError < StandardError
176
176
  def initialize
177
177
  super "Could not concatenate to the buffer because it is not html safe."
@@ -212,27 +212,30 @@ module ActiveSupport #:nodoc:
212
212
  end
213
213
 
214
214
  def concat(value)
215
- super(html_escape_interpolated_argument(value))
215
+ unless value.nil?
216
+ super(implicit_html_escape_interpolated_argument(value))
217
+ end
218
+ self
216
219
  end
217
220
  alias << concat
218
221
 
219
222
  def insert(index, value)
220
- super(index, html_escape_interpolated_argument(value))
223
+ super(index, implicit_html_escape_interpolated_argument(value))
221
224
  end
222
225
 
223
226
  def prepend(value)
224
- super(html_escape_interpolated_argument(value))
227
+ super(implicit_html_escape_interpolated_argument(value))
225
228
  end
226
229
 
227
230
  def replace(value)
228
- super(html_escape_interpolated_argument(value))
231
+ super(implicit_html_escape_interpolated_argument(value))
229
232
  end
230
233
 
231
234
  def []=(*args)
232
235
  if args.length == 3
233
- super(args[0], args[1], html_escape_interpolated_argument(args[2]))
236
+ super(args[0], args[1], implicit_html_escape_interpolated_argument(args[2]))
234
237
  else
235
- super(args[0], html_escape_interpolated_argument(args[1]))
238
+ super(args[0], implicit_html_escape_interpolated_argument(args[1]))
236
239
  end
237
240
  end
238
241
 
@@ -250,9 +253,9 @@ module ActiveSupport #:nodoc:
250
253
  def %(args)
251
254
  case args
252
255
  when Hash
253
- escaped_args = args.transform_values { |arg| html_escape_interpolated_argument(arg) }
256
+ escaped_args = args.transform_values { |arg| explicit_html_escape_interpolated_argument(arg) }
254
257
  else
255
- escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
258
+ escaped_args = Array(args).map { |arg| explicit_html_escape_interpolated_argument(arg) }
256
259
  end
257
260
 
258
261
  self.class.new(super(escaped_args))
@@ -290,39 +293,60 @@ module ActiveSupport #:nodoc:
290
293
  end
291
294
 
292
295
  UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
293
- if unsafe_method.respond_to?(unsafe_method)
294
- class_eval <<-EOT, __FILE__, __LINE__ + 1
295
- def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
296
- if block # if block
297
- to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
298
- set_block_back_references(block, $~) # set_block_back_references(block, $~)
299
- block.call(*params) # block.call(*params)
300
- } # }
301
- else # else
302
- to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
303
- end # end
304
- end # end
305
-
306
- def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
307
- @html_safe = false # @html_safe = false
308
- if block # if block
309
- super(*args) { |*params| # super(*args) { |*params|
310
- set_block_back_references(block, $~) # set_block_back_references(block, $~)
311
- block.call(*params) # block.call(*params)
312
- } # }
313
- else # else
314
- super # super
315
- end # end
316
- end # end
317
- EOT
318
- end
296
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
297
+ def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
298
+ if block # if block
299
+ to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
300
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
301
+ block.call(*params) # block.call(*params)
302
+ } # }
303
+ else # else
304
+ to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
305
+ end # end
306
+ end # end
307
+
308
+ def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
309
+ @html_safe = false # @html_safe = false
310
+ if block # if block
311
+ super(*args) { |*params| # super(*args) { |*params|
312
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
313
+ block.call(*params) # block.call(*params)
314
+ } # }
315
+ else # else
316
+ super # super
317
+ end # end
318
+ end # end
319
+ EOT
319
320
  end
320
321
 
321
322
  private
322
- def html_escape_interpolated_argument(arg)
323
+ def explicit_html_escape_interpolated_argument(arg)
323
324
  (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
324
325
  end
325
326
 
327
+ def implicit_html_escape_interpolated_argument(arg)
328
+ if !html_safe? || arg.html_safe?
329
+ arg
330
+ else
331
+ arg_string = begin
332
+ arg.to_str
333
+ rescue NoMethodError => error
334
+ if error.name == :to_str
335
+ str = arg.to_s
336
+ ActiveSupport::Deprecation.warn <<~MSG.squish
337
+ Implicit conversion of #{arg.class} into String by ActiveSupport::SafeBuffer
338
+ is deprecated and will be removed in Rails 7.1.
339
+ You must explicitly cast it to a String.
340
+ MSG
341
+ str
342
+ else
343
+ raise
344
+ end
345
+ end
346
+ CGI.escapeHTML(arg_string)
347
+ end
348
+ end
349
+
326
350
  def set_block_back_references(block, match_data)
327
351
  block.binding.eval("proc { |m| $~ = m }").call(match_data)
328
352
  rescue ArgumentError
@@ -1,14 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Symbol
4
- def start_with?(*prefixes)
5
- to_s.start_with?(*prefixes)
6
- end unless method_defined?(:start_with?)
7
-
8
- def end_with?(*suffixes)
9
- to_s.end_with?(*suffixes)
10
- end unless method_defined?(:end_with?)
11
-
12
4
  alias :starts_with? :start_with?
13
5
  alias :ends_with? :end_with?
14
6
  end
@@ -42,8 +42,8 @@ class Time
42
42
 
43
43
  # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
44
44
  # instances can be used when called with a single argument
45
- def at_with_coercion(*args)
46
- 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?
47
47
 
48
48
  # Time.at can be called with a time or numerical value
49
49
  time_or_number = args.first
@@ -56,7 +56,6 @@ class Time
56
56
  at_without_coercion(time_or_number)
57
57
  end
58
58
  end
59
- ruby2_keywords(:at_with_coercion) if respond_to?(:ruby2_keywords, true)
60
59
  alias_method :at_without_coercion, :at
61
60
  alias_method :at, :at_with_coercion
62
61
 
@@ -127,8 +126,8 @@ class Time
127
126
  # Returns a new Time where one or more of the elements have been changed according
128
127
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
129
128
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
130
- # the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
131
- # and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
129
+ # the hour is passed, then minute, sec, usec, and nsec is set to 0. If the hour
130
+ # and minute is passed, then sec, usec, and nsec is set to 0. The +options+ parameter
132
131
  # takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
133
132
  # <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
134
133
  # <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
@@ -278,7 +277,7 @@ class Time
278
277
  end
279
278
  alias :at_end_of_minute :end_of_minute
280
279
 
281
- def plus_with_duration(other) #:nodoc:
280
+ def plus_with_duration(other) # :nodoc:
282
281
  if ActiveSupport::Duration === other
283
282
  other.since(self)
284
283
  else
@@ -288,7 +287,7 @@ class Time
288
287
  alias_method :plus_without_duration, :+
289
288
  alias_method :+, :plus_with_duration
290
289
 
291
- def minus_with_duration(other) #:nodoc:
290
+ def minus_with_duration(other) # :nodoc:
292
291
  if ActiveSupport::Duration === other
293
292
  other.until(self)
294
293
  else
@@ -306,7 +305,7 @@ class Time
306
305
  other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
307
306
  end
308
307
  alias_method :minus_without_coercion, :-
309
- alias_method :-, :minus_with_coercion
308
+ alias_method :-, :minus_with_coercion # rubocop:disable Lint/DuplicateMethods
310
309
 
311
310
  # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
312
311
  # can be chronologically compared with a Time
@@ -27,22 +27,22 @@ class Time
27
27
 
28
28
  # Converts to a formatted string. See DATE_FORMATS for built-in formats.
29
29
  #
30
- # This method is aliased to <tt>to_s</tt>.
30
+ # This method is aliased to <tt>to_formatted_s</tt>.
31
31
  #
32
32
  # time = Time.now # => 2007-01-18 06:10:17 -06:00
33
33
  #
34
+ # time.to_fs(:time) # => "06:10"
34
35
  # time.to_formatted_s(:time) # => "06:10"
35
- # time.to_s(:time) # => "06:10"
36
36
  #
37
- # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
38
- # time.to_formatted_s(:number) # => "20070118061017"
39
- # time.to_formatted_s(:short) # => "18 Jan 06:10"
40
- # time.to_formatted_s(:long) # => "January 18, 2007 06:10"
41
- # time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
42
- # time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
43
- # time.to_formatted_s(:iso8601) # => "2007-01-18T06:10:17-06:00"
37
+ # time.to_fs(:db) # => "2007-01-18 06:10:17"
38
+ # time.to_fs(:number) # => "20070118061017"
39
+ # time.to_fs(:short) # => "18 Jan 06:10"
40
+ # time.to_fs(:long) # => "January 18, 2007 06:10"
41
+ # time.to_fs(:long_ordinal) # => "January 18th, 2007 06:10"
42
+ # time.to_fs(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
43
+ # time.to_fs(:iso8601) # => "2007-01-18T06:10:17-06:00"
44
44
  #
45
- # == Adding your own time formats to +to_formatted_s+
45
+ # == Adding your own time formats to +to_fs+
46
46
  # You can add your own formats to the Time::DATE_FORMATS hash.
47
47
  # Use the format name as the hash key and either a strftime string
48
48
  # or Proc instance that takes a time argument as the value.
@@ -50,15 +50,16 @@ class Time
50
50
  # # config/initializers/time_formats.rb
51
51
  # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
52
52
  # Time::DATE_FORMATS[:short_ordinal] = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
53
- def to_formatted_s(format = :default)
53
+ def to_fs(format = :default)
54
54
  if formatter = DATE_FORMATS[format]
55
55
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
56
56
  else
57
+ # Change to `to_s` when deprecation is gone. Also deprecate `to_default_s`.
57
58
  to_default_s
58
59
  end
59
60
  end
61
+ alias_method :to_formatted_s, :to_fs
60
62
  alias_method :to_default_s, :to_s
61
- alias_method :to_s, :to_formatted_s
62
63
 
63
64
  # Returns a formatted string of the offset from UTC, or an alternative
64
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_fs(#{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_fs(#{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.
@@ -21,8 +21,8 @@ class Time
21
21
  #
22
22
  # * A Rails TimeZone object.
23
23
  # * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
24
- # * A TZInfo::Timezone object.
25
- # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
24
+ # * A <tt>TZInfo::Timezone</tt> object.
25
+ # * An identifier for a <tt>TZInfo::Timezone</tt> object (e.g., "America/New_York").
26
26
  #
27
27
  # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis and reset it when the request is done.
28
28
  # <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
@@ -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;
@@ -55,7 +55,7 @@ class Time
55
55
  # end
56
56
  # end
57
57
  #
58
- # NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
58
+ # NOTE: This won't affect any ActiveSupport::TimeWithZone
59
59
  # objects that have already been created, e.g. any model timestamp
60
60
  # attributes that have been read before the block will remain in
61
61
  # the application's default timezone.
@@ -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,29 +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
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
23
- URI.parser is deprecated and will be removed in Rails 7.0.
24
- Use `URI::DEFAULT_PARSER` instead.
25
- MSG
26
- URI::DEFAULT_PARSER
27
- end
28
- end
29
- 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
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
@@ -98,25 +98,37 @@ module ActiveSupport
98
98
 
99
99
  # Declares one or more attributes that will be given both class and instance accessor methods.
100
100
  def attribute(*names)
101
- generated_attribute_methods.module_eval do
101
+ ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
102
102
  names.each do |name|
103
- define_method(name) do
104
- attributes[name.to_sym]
103
+ owner.define_cached_method(name, namespace: :current_attributes) do |batch|
104
+ batch <<
105
+ "def #{name}" <<
106
+ "attributes[:#{name}]" <<
107
+ "end"
105
108
  end
106
-
107
- define_method("#{name}=") do |attribute|
108
- attributes[name.to_sym] = attribute
109
+ owner.define_cached_method("#{name}=", namespace: :current_attributes) do |batch|
110
+ batch <<
111
+ "def #{name}=(value)" <<
112
+ "attributes[:#{name}] = value" <<
113
+ "end"
109
114
  end
110
115
  end
111
116
  end
112
117
 
113
- names.each do |name|
114
- define_singleton_method(name) do
115
- instance.public_send(name)
116
- end
117
-
118
- define_singleton_method("#{name}=") do |attribute|
119
- instance.public_send("#{name}=", attribute)
118
+ ActiveSupport::CodeGenerator.batch(singleton_class, __FILE__, __LINE__) do |owner|
119
+ names.each do |name|
120
+ owner.define_cached_method(name, namespace: :current_attributes_delegation) do |batch|
121
+ batch <<
122
+ "def #{name}" <<
123
+ "instance.#{name}" <<
124
+ "end"
125
+ end
126
+ owner.define_cached_method("#{name}=", namespace: :current_attributes_delegation) do |batch|
127
+ batch <<
128
+ "def #{name}=(value)" <<
129
+ "instance.#{name} = value" <<
130
+ "end"
131
+ end
120
132
  end
121
133
  end
122
134
  end
@@ -149,7 +161,7 @@ module ActiveSupport
149
161
  end
150
162
 
151
163
  def current_instances
152
- Thread.current[:current_attributes_instances] ||= {}
164
+ IsolatedExecutionState[:current_attributes_instances] ||= {}
153
165
  end
154
166
 
155
167
  def current_instances_key
@@ -164,6 +176,11 @@ module ActiveSupport
164
176
 
165
177
  send(name, *args, &block)
166
178
  end
179
+ ruby2_keywords(:method_missing)
180
+
181
+ def respond_to_missing?(name, _)
182
+ super || instance.respond_to?(name)
183
+ end
167
184
  end
168
185
 
169
186
  attr_accessor :attributes
@@ -2,23 +2,19 @@
2
2
 
3
3
  require "active_support/concurrency/share_lock"
4
4
 
5
- module ActiveSupport #:nodoc:
6
- module Dependencies #:nodoc:
5
+ module ActiveSupport # :nodoc:
6
+ module Dependencies # :nodoc:
7
7
  class Interlock
8
8
  def initialize # :nodoc:
9
9
  @lock = ActiveSupport::Concurrency::ShareLock.new
10
10
  end
11
11
 
12
- def loading
13
- @lock.exclusive(purpose: :load, compatible: [:load], after_compatible: [:load]) do
14
- yield
15
- end
12
+ def loading(&block)
13
+ @lock.exclusive(purpose: :load, compatible: [:load], after_compatible: [:load], &block)
16
14
  end
17
15
 
18
- def unloading
19
- @lock.exclusive(purpose: :unload, compatible: [:load, :unload], after_compatible: [:load, :unload]) do
20
- yield
21
- end
16
+ def unloading(&block)
17
+ @lock.exclusive(purpose: :unload, compatible: [:load, :unload], after_compatible: [:load, :unload], &block)
22
18
  end
23
19
 
24
20
  def start_unloading
@@ -37,16 +33,12 @@ module ActiveSupport #:nodoc:
37
33
  @lock.stop_sharing
38
34
  end
39
35
 
40
- def running
41
- @lock.sharing do
42
- yield
43
- end
36
+ def running(&block)
37
+ @lock.sharing(&block)
44
38
  end
45
39
 
46
- def permit_concurrent_loads
47
- @lock.yield_shares(compatible: [:load]) do
48
- yield
49
- end
40
+ def permit_concurrent_loads(&block)
41
+ @lock.yield_shares(compatible: [:load], &block)
50
42
  end
51
43
 
52
44
  def raw_state(&block) # :nodoc:
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport::Dependencies::RequireDependency
4
+ # <b>Warning:</b> This method is obsolete. The semantics of the autoloader
5
+ # match Ruby's and you do not need to be defensive with load order anymore.
6
+ # Just refer to classes and modules normally.
7
+ #
8
+ # Engines that do not control the mode in which their parent application runs
9
+ # should call +require_dependency+ where needed in case the runtime mode is
10
+ # +:classic+.
11
+ def require_dependency(filename)
12
+ filename = filename.to_path if filename.respond_to?(:to_path)
13
+
14
+ unless filename.is_a?(String)
15
+ raise ArgumentError, "the file name must be either a String or implement #to_path -- you passed #{filename.inspect}"
16
+ end
17
+
18
+ if abspath = ActiveSupport::Dependencies.search_for_file(filename)
19
+ require abspath
20
+ else
21
+ require filename
22
+ end
23
+ end
24
+
25
+ # We could define require_dependency in Object directly, but a module makes
26
+ # the extension apparent if you list ancestors.
27
+ Object.prepend(self)
28
+ end