activesupport 7.1.6 → 7.2.3

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +212 -1122
  3. data/README.rdoc +1 -1
  4. data/lib/active_support/array_inquirer.rb +1 -1
  5. data/lib/active_support/backtrace_cleaner.rb +10 -3
  6. data/lib/active_support/broadcast_logger.rb +65 -78
  7. data/lib/active_support/cache/file_store.rb +17 -12
  8. data/lib/active_support/cache/mem_cache_store.rb +29 -89
  9. data/lib/active_support/cache/memory_store.rb +7 -6
  10. data/lib/active_support/cache/null_store.rb +2 -2
  11. data/lib/active_support/cache/redis_cache_store.rb +17 -14
  12. data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
  13. data/lib/active_support/cache/strategy/local_cache.rb +56 -20
  14. data/lib/active_support/cache.rb +63 -71
  15. data/lib/active_support/callbacks.rb +77 -115
  16. data/lib/active_support/core_ext/array/conversions.rb +0 -2
  17. data/lib/active_support/core_ext/benchmark.rb +1 -0
  18. data/lib/active_support/core_ext/class/attribute.rb +2 -1
  19. data/lib/active_support/core_ext/class/subclasses.rb +15 -35
  20. data/lib/active_support/core_ext/date/blank.rb +4 -0
  21. data/lib/active_support/core_ext/date/conversions.rb +0 -2
  22. data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
  23. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  24. data/lib/active_support/core_ext/date_time/conversions.rb +4 -6
  25. data/lib/active_support/core_ext/digest/uuid.rb +6 -0
  26. data/lib/active_support/core_ext/enumerable.rb +17 -5
  27. data/lib/active_support/core_ext/erb/util.rb +7 -2
  28. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  29. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  30. data/lib/active_support/core_ext/module/delegation.rb +20 -163
  31. data/lib/active_support/core_ext/module/deprecation.rb +1 -4
  32. data/lib/active_support/core_ext/module/introspection.rb +3 -0
  33. data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
  34. data/lib/active_support/core_ext/object/blank.rb +45 -1
  35. data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
  36. data/lib/active_support/core_ext/object/json.rb +1 -1
  37. data/lib/active_support/core_ext/object/try.rb +2 -2
  38. data/lib/active_support/core_ext/object/with.rb +5 -3
  39. data/lib/active_support/core_ext/pathname/blank.rb +4 -0
  40. data/lib/active_support/core_ext/range/overlap.rb +1 -1
  41. data/lib/active_support/core_ext/range/sole.rb +17 -0
  42. data/lib/active_support/core_ext/range.rb +1 -0
  43. data/lib/active_support/core_ext/securerandom.rb +4 -4
  44. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  45. data/lib/active_support/core_ext/string/filters.rb +4 -4
  46. data/lib/active_support/core_ext/string/multibyte.rb +3 -3
  47. data/lib/active_support/core_ext/string/output_safety.rb +0 -7
  48. data/lib/active_support/core_ext/time/calculations.rb +18 -28
  49. data/lib/active_support/core_ext/time/compatibility.rb +24 -0
  50. data/lib/active_support/core_ext/time/conversions.rb +0 -2
  51. data/lib/active_support/core_ext/time/zones.rb +1 -1
  52. data/lib/active_support/core_ext.rb +0 -1
  53. data/lib/active_support/current_attributes.rb +45 -40
  54. data/lib/active_support/delegation.rb +202 -0
  55. data/lib/active_support/dependencies/autoload.rb +0 -12
  56. data/lib/active_support/deprecation/constant_accessor.rb +47 -26
  57. data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
  58. data/lib/active_support/deprecation/reporting.rb +7 -2
  59. data/lib/active_support/deprecation.rb +8 -5
  60. data/lib/active_support/descendants_tracker.rb +9 -87
  61. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  62. data/lib/active_support/duration/iso8601_serializer.rb +1 -2
  63. data/lib/active_support/duration.rb +11 -6
  64. data/lib/active_support/encrypted_file.rb +1 -1
  65. data/lib/active_support/error_reporter.rb +46 -5
  66. data/lib/active_support/evented_file_update_checker.rb +0 -1
  67. data/lib/active_support/execution_wrapper.rb +1 -2
  68. data/lib/active_support/file_update_checker.rb +2 -2
  69. data/lib/active_support/fork_tracker.rb +2 -38
  70. data/lib/active_support/gem_version.rb +2 -2
  71. data/lib/active_support/hash_with_indifferent_access.rb +26 -24
  72. data/lib/active_support/html_safe_translation.rb +3 -0
  73. data/lib/active_support/json/decoding.rb +1 -1
  74. data/lib/active_support/json/encoding.rb +23 -5
  75. data/lib/active_support/lazy_load_hooks.rb +1 -1
  76. data/lib/active_support/log_subscriber.rb +0 -12
  77. data/lib/active_support/logger.rb +15 -2
  78. data/lib/active_support/logger_thread_safe_level.rb +0 -8
  79. data/lib/active_support/message_encryptors.rb +2 -2
  80. data/lib/active_support/message_pack/extensions.rb +15 -2
  81. data/lib/active_support/message_verifier.rb +21 -0
  82. data/lib/active_support/message_verifiers.rb +5 -3
  83. data/lib/active_support/messages/rotator.rb +5 -0
  84. data/lib/active_support/multibyte/chars.rb +6 -3
  85. data/lib/active_support/notifications/fanout.rb +4 -7
  86. data/lib/active_support/notifications/instrumenter.rb +21 -18
  87. data/lib/active_support/notifications.rb +28 -27
  88. data/lib/active_support/number_helper/number_converter.rb +2 -2
  89. data/lib/active_support/option_merger.rb +2 -2
  90. data/lib/active_support/ordered_options.rb +53 -15
  91. data/lib/active_support/proxy_object.rb +8 -5
  92. data/lib/active_support/railtie.rb +4 -11
  93. data/lib/active_support/string_inquirer.rb +1 -1
  94. data/lib/active_support/subscriber.rb +1 -0
  95. data/lib/active_support/tagged_logging.rb +0 -1
  96. data/lib/active_support/test_case.rb +3 -1
  97. data/lib/active_support/testing/assertions.rb +4 -4
  98. data/lib/active_support/testing/constant_stubbing.rb +30 -8
  99. data/lib/active_support/testing/deprecation.rb +5 -12
  100. data/lib/active_support/testing/isolation.rb +20 -8
  101. data/lib/active_support/testing/method_call_assertions.rb +2 -16
  102. data/lib/active_support/testing/parallelization/server.rb +18 -2
  103. data/lib/active_support/testing/parallelization/worker.rb +2 -2
  104. data/lib/active_support/testing/parallelization.rb +12 -1
  105. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  106. data/lib/active_support/testing/time_helpers.rb +3 -3
  107. data/lib/active_support/time_with_zone.rb +8 -4
  108. data/lib/active_support/values/time_zone.rb +7 -7
  109. data/lib/active_support/xml_mini.rb +13 -2
  110. data/lib/active_support.rb +2 -1
  111. metadata +16 -24
  112. data/lib/active_support/deprecation/instance_delegator.rb +0 -65
  113. data/lib/active_support/ruby_features.rb +0 -7
  114. data/lib/active_support/testing/strict_warnings.rb +0 -39
@@ -15,17 +15,39 @@ module ActiveSupport
15
15
  # Using this method rather than forcing <tt>World::List::Import::LARGE_IMPORT_THRESHOLD = 5000</tt> prevents
16
16
  # warnings from being thrown, and ensures that the old value is returned after the test has completed.
17
17
  #
18
+ # If the constant doesn't already exists, but you need it set for the duration of the block
19
+ # you can do so by passing `exists: false`.
20
+ #
21
+ # stub_const(object, :SOME_CONST, 1, exists: false) do
22
+ # assert_equal 1, SOME_CONST
23
+ # end
24
+ #
18
25
  # Note: Stubbing a const will stub it across all threads. So if you have concurrent threads
19
26
  # (like separate test suites running in parallel) that all depend on the same constant, it's possible
20
27
  # divergent stubbing will trample on each other.
21
- def stub_const(mod, constant, new_value)
22
- old_value = mod.const_get(constant, false)
23
- mod.send(:remove_const, constant)
24
- mod.const_set(constant, new_value)
25
- yield
26
- ensure
27
- mod.send(:remove_const, constant)
28
- mod.const_set(constant, old_value)
28
+ def stub_const(mod, constant, new_value, exists: true)
29
+ if exists
30
+ begin
31
+ old_value = mod.const_get(constant, false)
32
+ mod.send(:remove_const, constant)
33
+ mod.const_set(constant, new_value)
34
+ yield
35
+ ensure
36
+ mod.send(:remove_const, constant)
37
+ mod.const_set(constant, old_value)
38
+ end
39
+ else
40
+ if mod.const_defined?(constant)
41
+ raise NameError, "already defined constant #{constant} in #{mod.name}"
42
+ end
43
+
44
+ begin
45
+ mod.const_set(constant, new_value)
46
+ yield
47
+ ensure
48
+ mod.send(:remove_const, constant)
49
+ end
50
+ end
29
51
  end
30
52
  end
31
53
  end
@@ -29,10 +29,11 @@ module ActiveSupport
29
29
  # end
30
30
  def assert_deprecated(match = nil, deprecator = nil, &block)
31
31
  match, deprecator = nil, match if match.is_a?(ActiveSupport::Deprecation)
32
+
32
33
  unless deprecator
33
- ActiveSupport.deprecator.warn("assert_deprecated without a deprecator is deprecated")
34
- deprecator = ActiveSupport::Deprecation._instance
34
+ raise ArgumentError, "No deprecator given"
35
35
  end
36
+
36
37
  result, warnings = collect_deprecations(deprecator, &block)
37
38
  assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
38
39
  if match
@@ -51,11 +52,7 @@ module ActiveSupport
51
52
  # assert_not_deprecated(ActiveSupport::Deprecation.new) do
52
53
  # CustomDeprecator.warn "message" # passes assertion, different deprecator
53
54
  # end
54
- def assert_not_deprecated(deprecator = nil, &block)
55
- unless deprecator
56
- ActiveSupport.deprecator.warn("assert_not_deprecated without a deprecator is deprecated")
57
- deprecator = ActiveSupport::Deprecation._instance
58
- end
55
+ def assert_not_deprecated(deprecator, &block)
59
56
  result, deprecations = collect_deprecations(deprecator, &block)
60
57
  assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
61
58
  result
@@ -69,11 +66,7 @@ module ActiveSupport
69
66
  # ActiveSupport::Deprecation.new.warn "other message"
70
67
  # :result
71
68
  # end # => [:result, ["message"]]
72
- def collect_deprecations(deprecator = nil)
73
- unless deprecator
74
- ActiveSupport.deprecator.warn("collect_deprecations without a deprecator is deprecated")
75
- deprecator = ActiveSupport::Deprecation._instance
76
- end
69
+ def collect_deprecations(deprecator)
77
70
  old_behavior = deprecator.behavior
78
71
  deprecations = []
79
72
  deprecator.behavior = Proc.new do |message, callstack|
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/testing/parallelize_executor"
4
+
3
5
  module ActiveSupport
4
6
  module Testing
5
7
  module Isolation
6
8
  require "thread"
7
9
 
10
+ SubprocessCrashed = Class.new(StandardError)
11
+
8
12
  def self.included(klass) # :nodoc:
9
13
  klass.class_eval do
10
- parallelize_me!
14
+ parallelize_me! unless Minitest.parallel_executor.is_a?(ActiveSupport::Testing::ParallelizeExecutor)
11
15
  end
12
16
  end
13
17
 
@@ -16,10 +20,17 @@ module ActiveSupport
16
20
  end
17
21
 
18
22
  def run
19
- serialized = run_in_isolation do
23
+ status, serialized = run_in_isolation do
20
24
  super
21
25
  end
22
26
 
27
+ unless status&.success?
28
+ error = SubprocessCrashed.new("Subprocess exited with an error: #{status.inspect}\noutput: #{serialized.inspect}")
29
+ error.set_backtrace(caller)
30
+ self.failures << Minitest::UnexpectedError.new(error)
31
+ return defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
32
+ end
33
+
23
34
  Marshal.load(serialized)
24
35
  end
25
36
 
@@ -50,13 +61,13 @@ module ActiveSupport
50
61
  end
51
62
 
52
63
  write.puts [result].pack("m")
53
- exit!
64
+ exit!(0)
54
65
  end
55
66
 
56
67
  write.close
57
68
  result = read.read
58
- Process.wait2(pid)
59
- result.unpack1("m")
69
+ _, status = Process.wait2(pid)
70
+ return status, result.unpack1("m")
60
71
  end
61
72
  end
62
73
  end
@@ -75,7 +86,7 @@ module ActiveSupport
75
86
  File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
76
87
  file.puts [Marshal.dump(test_result)].pack("m")
77
88
  end
78
- exit!
89
+ exit!(0)
79
90
  else
80
91
  Tempfile.open("isolation") do |tmpfile|
81
92
  env = {
@@ -93,13 +104,14 @@ module ActiveSupport
93
104
 
94
105
  child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
95
106
 
107
+ status = nil
96
108
  begin
97
- Process.wait(child.pid)
109
+ _, status = Process.wait2(child.pid)
98
110
  rescue Errno::ECHILD # The child process may exit before we wait
99
111
  nil
100
112
  end
101
113
 
102
- return tmpfile.read.unpack1("m")
114
+ return status, tmpfile.read.unpack1("m")
103
115
  end
104
116
  end
105
117
  end
@@ -30,22 +30,8 @@ module ActiveSupport
30
30
  assert_called(object, method_name, message, times: 0, &block)
31
31
  end
32
32
 
33
- #--
34
- # This method is a temporary wrapper for mock.expect as part of
35
- # the Minitest 5.16 / Ruby 3.0 kwargs transition. It can go away
36
- # when we drop support for Ruby 2.7.
37
- if Minitest::Mock.instance_method(:expect).parameters.map(&:first).include?(:keyrest)
38
- def expect_called_with(mock, args, returns: false, **kwargs)
39
- mock.expect(:call, returns, args, **kwargs)
40
- end
41
- else
42
- def expect_called_with(mock, args, returns: false, **kwargs)
43
- if !kwargs.empty?
44
- mock.expect(:call, returns, [*args, kwargs])
45
- else
46
- mock.expect(:call, returns, args)
47
- end
48
- end
33
+ def expect_called_with(mock, args, returns: false, **kwargs)
34
+ mock.expect(:call, returns, args, **kwargs)
49
35
  end
50
36
 
51
37
  def assert_called_on_instance_of(klass, method_name, message = nil, times: 1, returns: nil)
@@ -6,12 +6,15 @@ require "drb/unix" unless Gem.win_platform?
6
6
  module ActiveSupport
7
7
  module Testing
8
8
  class Parallelization # :nodoc:
9
+ PrerecordResultClass = Struct.new(:name)
10
+
9
11
  class Server
10
12
  include DRb::DRbUndumped
11
13
 
12
14
  def initialize
13
15
  @queue = Queue.new
14
16
  @active_workers = Concurrent::Map.new
17
+ @worker_pids = Concurrent::Map.new
15
18
  @in_flight = Concurrent::Map.new
16
19
  end
17
20
 
@@ -21,6 +24,7 @@ module ActiveSupport
21
24
  @in_flight.delete([result.klass, result.name])
22
25
 
23
26
  reporter.synchronize do
27
+ reporter.prerecord(PrerecordResultClass.new(result.klass), result.name)
24
28
  reporter.record(result)
25
29
  end
26
30
  end
@@ -37,12 +41,24 @@ module ActiveSupport
37
41
  end
38
42
  end
39
43
 
40
- def start_worker(worker_id)
44
+ def start_worker(worker_id, worker_pid)
41
45
  @active_workers[worker_id] = true
46
+ @worker_pids[worker_id] = worker_pid
42
47
  end
43
48
 
44
- def stop_worker(worker_id)
49
+ def stop_worker(worker_id, worker_pid)
45
50
  @active_workers.delete(worker_id)
51
+ @worker_pids.delete(worker_id)
52
+ end
53
+
54
+ def remove_dead_workers(dead_pids)
55
+ dead_pids.each do |dead_pid|
56
+ worker_id = @worker_pids.key(dead_pid)
57
+ if worker_id
58
+ @active_workers.delete(worker_id)
59
+ @worker_pids.delete(worker_id)
60
+ end
61
+ end
46
62
  end
47
63
 
48
64
  def active_workers?
@@ -18,7 +18,7 @@ module ActiveSupport
18
18
  DRb.stop_service
19
19
 
20
20
  @queue = DRbObject.new_with_uri(@url)
21
- @queue.start_worker(@id)
21
+ @queue.start_worker(@id, Process.pid)
22
22
 
23
23
  begin
24
24
  after_fork
@@ -29,7 +29,7 @@ module ActiveSupport
29
29
  set_process_title("(stopping)")
30
30
 
31
31
  run_cleanup
32
- @queue.stop_worker(@id)
32
+ @queue.stop_worker(@id, Process.pid)
33
33
  end
34
34
  end
35
35
 
@@ -47,8 +47,19 @@ module ActiveSupport
47
47
  end
48
48
 
49
49
  def shutdown
50
+ dead_worker_pids = @worker_pool.filter_map do |pid|
51
+ Process.waitpid(pid, Process::WNOHANG)
52
+ rescue Errno::ECHILD
53
+ pid
54
+ end
55
+ @queue_server.remove_dead_workers(dead_worker_pids)
56
+
50
57
  @queue_server.shutdown
51
- @worker_pool.each { |pid| Process.waitpid pid }
58
+ @worker_pool.each do |pid|
59
+ Process.waitpid(pid)
60
+ rescue Errno::ECHILD
61
+ nil
62
+ end
52
63
  end
53
64
  end
54
65
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ # Warns when a test case does not perform any assertions.
6
+ #
7
+ # This is helpful in detecting broken tests that do not perform intended assertions.
8
+ module TestsWithoutAssertions # :nodoc:
9
+ def after_teardown
10
+ super
11
+
12
+ if assertions.zero? && !skipped? && !error?
13
+ file, line = method(name).source_location
14
+ warn "Test is missing assertions: `#{name}` #{file}:#{line}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -163,10 +163,10 @@ module ActiveSupport
163
163
  now = date_or_time.midnight.to_time
164
164
  elsif date_or_time.is_a?(String)
165
165
  now = Time.zone.parse(date_or_time)
166
- elsif with_usec
167
- now = date_or_time.to_time
168
166
  else
169
- now = date_or_time.to_time.change(usec: 0)
167
+ now = date_or_time
168
+ now = now.to_time unless now.is_a?(Time)
169
+ now = now.change(usec: 0) unless with_usec
170
170
  end
171
171
 
172
172
  # +now+ must be in local system timezone, because +Time.at(now)+
@@ -85,7 +85,7 @@ module ActiveSupport
85
85
  end
86
86
  alias_method :getlocal, :localtime
87
87
 
88
- # Returns true if the current time is within Daylight Savings Time for the
88
+ # Returns true if the current time is within Daylight Savings \Time for the
89
89
  # specified time zone.
90
90
  #
91
91
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
@@ -332,7 +332,7 @@ module ActiveSupport
332
332
  #
333
333
  def -(other)
334
334
  if other.acts_like?(:time)
335
- to_time - other.to_time
335
+ getutc - other.getutc
336
336
  elsif duration_of_variable_length?(other)
337
337
  method_missing(:-, other)
338
338
  else
@@ -375,8 +375,8 @@ module ActiveSupport
375
375
  #
376
376
  # t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15.116992711 EST -05:00
377
377
  # t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15.116992711 EST -05:00
378
- # t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00.116992711 EST -05:00
379
- # t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00.116992711 EST -05:00
378
+ # t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00.000000000 EST -05:00
379
+ # t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00.000000000 EST -05:00
380
380
  # t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
381
381
  # t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
382
382
  def change(options)
@@ -506,6 +506,10 @@ module ActiveSupport
506
506
  false
507
507
  end
508
508
 
509
+ def present? # :nodoc:
510
+ true
511
+ end
512
+
509
513
  def freeze
510
514
  # preload instance variables before freezing
511
515
  period; utc; time; to_datetime; to_time
@@ -12,7 +12,7 @@ module ActiveSupport
12
12
  # * Limit the set of zones provided by TZInfo to a meaningful subset of 134
13
13
  # zones.
14
14
  # * Retrieve and display zones with a friendlier name
15
- # (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
15
+ # (e.g., "Eastern \Time (US & Canada)" instead of "America/New_York").
16
16
  # * Lazily load +TZInfo::Timezone+ instances only when they're needed.
17
17
  # * Create ActiveSupport::TimeWithZone instances via TimeZone's +local+,
18
18
  # +parse+, +at+, and +now+ methods.
@@ -134,10 +134,10 @@ module ActiveSupport
134
134
  "Mumbai" => "Asia/Kolkata",
135
135
  "New Delhi" => "Asia/Kolkata",
136
136
  "Kathmandu" => "Asia/Kathmandu",
137
- "Astana" => "Asia/Dhaka",
138
137
  "Dhaka" => "Asia/Dhaka",
139
138
  "Sri Jayawardenepura" => "Asia/Colombo",
140
139
  "Almaty" => "Asia/Almaty",
140
+ "Astana" => "Asia/Almaty",
141
141
  "Novosibirsk" => "Asia/Novosibirsk",
142
142
  "Rangoon" => "Asia/Rangoon",
143
143
  "Bangkok" => "Asia/Bangkok",
@@ -357,7 +357,7 @@ module ActiveSupport
357
357
  "(GMT#{formatted_offset}) #{name}"
358
358
  end
359
359
 
360
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
360
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
361
361
  # of +self+ from given values.
362
362
  #
363
363
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -367,7 +367,7 @@ module ActiveSupport
367
367
  ActiveSupport::TimeWithZone.new(nil, self, time)
368
368
  end
369
369
 
370
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
370
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
371
371
  # of +self+ from number of seconds since the Unix epoch.
372
372
  #
373
373
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -382,7 +382,7 @@ module ActiveSupport
382
382
  Time.at(*args).utc.in_time_zone(self)
383
383
  end
384
384
 
385
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
385
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
386
386
  # of +self+ from an ISO 8601 string.
387
387
  #
388
388
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -434,7 +434,7 @@ module ActiveSupport
434
434
  raise ArgumentError, "invalid date"
435
435
  end
436
436
 
437
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
437
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
438
438
  # of +self+ from parsed string.
439
439
  #
440
440
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -456,7 +456,7 @@ module ActiveSupport
456
456
  parts_to_time(Date._parse(str, false), now)
457
457
  end
458
458
 
459
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
459
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
460
460
  # of +self+ from an RFC 3339 string.
461
461
  #
462
462
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -12,7 +12,7 @@ module ActiveSupport
12
12
  # = \XmlMini
13
13
  #
14
14
  # To use the much faster libxml parser:
15
- # gem 'libxml-ruby'
15
+ # gem "libxml-ruby"
16
16
  # XmlMini.backend = 'LibXML'
17
17
  module XmlMini
18
18
  extend self
@@ -46,6 +46,7 @@ module ActiveSupport
46
46
  "Date" => "date",
47
47
  "DateTime" => "dateTime",
48
48
  "Time" => "dateTime",
49
+ "ActiveSupport::Duration" => "duration",
49
50
  "Array" => "array",
50
51
  "Hash" => "hash"
51
52
  }
@@ -56,6 +57,7 @@ module ActiveSupport
56
57
  "symbol" => Proc.new { |symbol| symbol.to_s },
57
58
  "date" => Proc.new { |date| date.to_fs(:db) },
58
59
  "dateTime" => Proc.new { |time| time.xmlschema },
60
+ "duration" => Proc.new { |duration| duration.iso8601 },
59
61
  "binary" => Proc.new { |binary| ::Base64.encode64(binary) },
60
62
  "yaml" => Proc.new { |yaml| yaml.to_yaml }
61
63
  } unless defined?(FORMATTING)
@@ -66,11 +68,14 @@ module ActiveSupport
66
68
  "symbol" => Proc.new { |symbol| symbol.to_s.to_sym },
67
69
  "date" => Proc.new { |date| ::Date.parse(date) },
68
70
  "datetime" => Proc.new { |time| Time.xmlschema(time).utc rescue ::DateTime.parse(time).utc },
71
+ "duration" => Proc.new { |duration| Duration.parse(duration) },
69
72
  "integer" => Proc.new { |integer| integer.to_i },
70
73
  "float" => Proc.new { |float| float.to_f },
71
74
  "decimal" => Proc.new do |number|
72
75
  if String === number
73
76
  number.to_d
77
+ elsif Float === number
78
+ BigDecimal(number, 0)
74
79
  else
75
80
  BigDecimal(number)
76
81
  end
@@ -79,6 +84,7 @@ module ActiveSupport
79
84
  "string" => Proc.new { |string| string.to_s },
80
85
  "yaml" => Proc.new { |yaml| YAML.load(yaml) rescue yaml },
81
86
  "base64Binary" => Proc.new { |bin| ::Base64.decode64(bin) },
87
+ "hexBinary" => Proc.new { |bin| _parse_hex_binary(bin) },
82
88
  "binary" => Proc.new { |bin, entity| _parse_binary(bin, entity) },
83
89
  "file" => Proc.new { |file, entity| _parse_file(file, entity) }
84
90
  }
@@ -162,11 +168,12 @@ module ActiveSupport
162
168
  "#{left}#{middle.tr('_ ', '--')}#{right}"
163
169
  end
164
170
 
165
- # TODO: Add support for other encodings
166
171
  def _parse_binary(bin, entity)
167
172
  case entity["encoding"]
168
173
  when "base64"
169
174
  ::Base64.decode64(bin)
175
+ when "hex", "hexBinary"
176
+ _parse_hex_binary(bin)
170
177
  else
171
178
  bin
172
179
  end
@@ -180,6 +187,10 @@ module ActiveSupport
180
187
  f
181
188
  end
182
189
 
190
+ def _parse_hex_binary(bin)
191
+ [bin].pack("H*")
192
+ end
193
+
183
194
  def current_thread_backend
184
195
  IsolatedExecutionState[:xml_mini_backend]
185
196
  end
@@ -63,6 +63,7 @@ module ActiveSupport
63
63
  autoload :Callbacks
64
64
  autoload :Configurable
65
65
  autoload :Deprecation
66
+ autoload :Delegation
66
67
  autoload :Digest
67
68
  autoload :ExecutionContext
68
69
  autoload :Gzip
@@ -116,7 +117,7 @@ module ActiveSupport
116
117
  def self.to_time_preserves_timezone=(value)
117
118
  unless value
118
119
  ActiveSupport.deprecator.warn(
119
- "Support for the pre-Ruby 2.4 behavior of to_time has been deprecated and will be removed in Rails 7.2."
120
+ "Support for the pre-Ruby 2.4 behavior of to_time has been deprecated and will be removed in Rails 8.0."
120
121
  )
121
122
  end
122
123
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesupport
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.6
4
+ version: 7.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -36,6 +36,9 @@ dependencies:
36
36
  - - "~>"
37
37
  - !ruby/object:Gem::Version
38
38
  version: '2.0'
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 2.0.5
39
42
  type: :runtime
40
43
  prerelease: false
41
44
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,6 +46,9 @@ dependencies:
43
46
  - - "~>"
44
47
  - !ruby/object:Gem::Version
45
48
  version: '2.0'
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 2.0.5
46
52
  - !ruby/object:Gem::Dependency
47
53
  name: concurrent-ruby
48
54
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +58,7 @@ dependencies:
52
58
  version: '1.0'
53
59
  - - ">="
54
60
  - !ruby/object:Gem::Version
55
- version: 1.0.2
61
+ version: 1.3.1
56
62
  type: :runtime
57
63
  prerelease: false
58
64
  version_requirements: !ruby/object:Gem::Requirement
@@ -62,7 +68,7 @@ dependencies:
62
68
  version: '1.0'
63
69
  - - ">="
64
70
  - !ruby/object:Gem::Version
65
- version: 1.0.2
71
+ version: 1.3.1
66
72
  - !ruby/object:Gem::Dependency
67
73
  name: connection_pool
68
74
  requirement: !ruby/object:Gem::Requirement
@@ -119,20 +125,6 @@ dependencies:
119
125
  - - ">="
120
126
  - !ruby/object:Gem::Version
121
127
  version: '0'
122
- - !ruby/object:Gem::Dependency
123
- name: mutex_m
124
- requirement: !ruby/object:Gem::Requirement
125
- requirements:
126
- - - ">="
127
- - !ruby/object:Gem::Version
128
- version: '0'
129
- type: :runtime
130
- prerelease: false
131
- version_requirements: !ruby/object:Gem::Requirement
132
- requirements:
133
- - - ">="
134
- - !ruby/object:Gem::Version
135
- version: '0'
136
128
  - !ruby/object:Gem::Dependency
137
129
  name: bigdecimal
138
130
  requirement: !ruby/object:Gem::Requirement
@@ -321,6 +313,7 @@ files:
321
313
  - lib/active_support/core_ext/range/conversions.rb
322
314
  - lib/active_support/core_ext/range/each.rb
323
315
  - lib/active_support/core_ext/range/overlap.rb
316
+ - lib/active_support/core_ext/range/sole.rb
324
317
  - lib/active_support/core_ext/regexp.rb
325
318
  - lib/active_support/core_ext/securerandom.rb
326
319
  - lib/active_support/core_ext/string.rb
@@ -349,6 +342,7 @@ files:
349
342
  - lib/active_support/current_attributes.rb
350
343
  - lib/active_support/current_attributes/test_helper.rb
351
344
  - lib/active_support/deep_mergeable.rb
345
+ - lib/active_support/delegation.rb
352
346
  - lib/active_support/dependencies.rb
353
347
  - lib/active_support/dependencies/autoload.rb
354
348
  - lib/active_support/dependencies/interlock.rb
@@ -358,7 +352,6 @@ files:
358
352
  - lib/active_support/deprecation/constant_accessor.rb
359
353
  - lib/active_support/deprecation/deprecators.rb
360
354
  - lib/active_support/deprecation/disallowed.rb
361
- - lib/active_support/deprecation/instance_delegator.rb
362
355
  - lib/active_support/deprecation/method_wrappers.rb
363
356
  - lib/active_support/deprecation/proxy_wrappers.rb
364
357
  - lib/active_support/deprecation/reporting.rb
@@ -444,7 +437,6 @@ files:
444
437
  - lib/active_support/railtie.rb
445
438
  - lib/active_support/reloader.rb
446
439
  - lib/active_support/rescuable.rb
447
- - lib/active_support/ruby_features.rb
448
440
  - lib/active_support/secure_compare_rotator.rb
449
441
  - lib/active_support/security_utils.rb
450
442
  - lib/active_support/string_inquirer.rb
@@ -468,8 +460,8 @@ files:
468
460
  - lib/active_support/testing/parallelize_executor.rb
469
461
  - lib/active_support/testing/setup_and_teardown.rb
470
462
  - lib/active_support/testing/stream.rb
471
- - lib/active_support/testing/strict_warnings.rb
472
463
  - lib/active_support/testing/tagged_logging.rb
464
+ - lib/active_support/testing/tests_without_assertions.rb
473
465
  - lib/active_support/testing/time_helpers.rb
474
466
  - lib/active_support/time.rb
475
467
  - lib/active_support/time_with_zone.rb
@@ -487,10 +479,10 @@ licenses:
487
479
  - MIT
488
480
  metadata:
489
481
  bug_tracker_uri: https://github.com/rails/rails/issues
490
- changelog_uri: https://github.com/rails/rails/blob/v7.1.6/activesupport/CHANGELOG.md
491
- documentation_uri: https://api.rubyonrails.org/v7.1.6/
482
+ changelog_uri: https://github.com/rails/rails/blob/v7.2.3/activesupport/CHANGELOG.md
483
+ documentation_uri: https://api.rubyonrails.org/v7.2.3/
492
484
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
493
- source_code_uri: https://github.com/rails/rails/tree/v7.1.6/activesupport
485
+ source_code_uri: https://github.com/rails/rails/tree/v7.2.3/activesupport
494
486
  rubygems_mfa_required: 'true'
495
487
  rdoc_options:
496
488
  - "--encoding"
@@ -501,7 +493,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
501
493
  requirements:
502
494
  - - ">="
503
495
  - !ruby/object:Gem::Version
504
- version: 2.7.0
496
+ version: 3.1.0
505
497
  required_rubygems_version: !ruby/object:Gem::Requirement
506
498
  requirements:
507
499
  - - ">="