activesupport 6.1.0 → 7.1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1075 -325
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/lib/active_support/actionable_error.rb +4 -2
  6. data/lib/active_support/array_inquirer.rb +2 -2
  7. data/lib/active_support/backtrace_cleaner.rb +32 -7
  8. data/lib/active_support/benchmarkable.rb +3 -2
  9. data/lib/active_support/broadcast_logger.rb +251 -0
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache/coder.rb +153 -0
  12. data/lib/active_support/cache/entry.rb +134 -0
  13. data/lib/active_support/cache/file_store.rb +53 -20
  14. data/lib/active_support/cache/mem_cache_store.rb +201 -62
  15. data/lib/active_support/cache/memory_store.rb +86 -24
  16. data/lib/active_support/cache/null_store.rb +16 -2
  17. data/lib/active_support/cache/redis_cache_store.rb +186 -193
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +63 -71
  20. data/lib/active_support/cache.rb +487 -249
  21. data/lib/active_support/callbacks.rb +227 -105
  22. data/lib/active_support/code_generator.rb +70 -0
  23. data/lib/active_support/concern.rb +9 -7
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/concurrency/share_lock.rb +2 -2
  27. data/lib/active_support/configurable.rb +18 -5
  28. data/lib/active_support/configuration_file.rb +7 -2
  29. data/lib/active_support/core_ext/array/access.rb +1 -5
  30. data/lib/active_support/core_ext/array/conversions.rb +15 -13
  31. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  33. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  34. data/lib/active_support/core_ext/class/subclasses.rb +37 -26
  35. data/lib/active_support/core_ext/date/blank.rb +1 -1
  36. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  37. data/lib/active_support/core_ext/date/conversions.rb +16 -15
  38. data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
  39. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  40. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  41. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  42. data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
  43. data/lib/active_support/core_ext/digest/uuid.rb +30 -13
  44. data/lib/active_support/core_ext/enumerable.rb +85 -83
  45. data/lib/active_support/core_ext/erb/util.rb +196 -0
  46. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  47. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  48. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  49. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  50. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  51. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  52. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  53. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  54. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  55. data/lib/active_support/core_ext/module/attribute_accessors.rb +8 -0
  56. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +49 -22
  57. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  58. data/lib/active_support/core_ext/module/delegation.rb +81 -43
  59. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  60. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  61. data/lib/active_support/core_ext/name_error.rb +2 -8
  62. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  63. data/lib/active_support/core_ext/numeric/conversions.rb +82 -77
  64. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  65. data/lib/active_support/core_ext/object/blank.rb +2 -2
  66. data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
  67. data/lib/active_support/core_ext/object/duplicable.rb +31 -11
  68. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  69. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  70. data/lib/active_support/core_ext/object/json.rb +49 -27
  71. data/lib/active_support/core_ext/object/to_query.rb +2 -4
  72. data/lib/active_support/core_ext/object/try.rb +20 -20
  73. data/lib/active_support/core_ext/object/with.rb +44 -0
  74. data/lib/active_support/core_ext/object/with_options.rb +25 -6
  75. data/lib/active_support/core_ext/object.rb +1 -0
  76. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  77. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  78. data/lib/active_support/core_ext/pathname.rb +4 -0
  79. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  80. data/lib/active_support/core_ext/range/conversions.rb +34 -13
  81. data/lib/active_support/core_ext/range/each.rb +1 -1
  82. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  83. data/lib/active_support/core_ext/range.rb +1 -2
  84. data/lib/active_support/core_ext/securerandom.rb +25 -13
  85. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  86. data/lib/active_support/core_ext/string/filters.rb +21 -15
  87. data/lib/active_support/core_ext/string/indent.rb +1 -1
  88. data/lib/active_support/core_ext/string/inflections.rb +17 -10
  89. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  90. data/lib/active_support/core_ext/string/output_safety.rb +85 -165
  91. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  92. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  93. data/lib/active_support/core_ext/time/calculations.rb +30 -8
  94. data/lib/active_support/core_ext/time/conversions.rb +15 -13
  95. data/lib/active_support/core_ext/time/zones.rb +12 -28
  96. data/lib/active_support/core_ext.rb +2 -1
  97. data/lib/active_support/current_attributes.rb +47 -20
  98. data/lib/active_support/deep_mergeable.rb +53 -0
  99. data/lib/active_support/dependencies/autoload.rb +17 -12
  100. data/lib/active_support/dependencies/interlock.rb +10 -18
  101. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  102. data/lib/active_support/dependencies.rb +58 -788
  103. data/lib/active_support/deprecation/behaviors.rb +66 -40
  104. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  105. data/lib/active_support/deprecation/deprecators.rb +104 -0
  106. data/lib/active_support/deprecation/disallowed.rb +6 -8
  107. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  108. data/lib/active_support/deprecation/method_wrappers.rb +9 -26
  109. data/lib/active_support/deprecation/proxy_wrappers.rb +38 -23
  110. data/lib/active_support/deprecation/reporting.rb +43 -26
  111. data/lib/active_support/deprecation.rb +32 -5
  112. data/lib/active_support/deprecator.rb +7 -0
  113. data/lib/active_support/descendants_tracker.rb +150 -72
  114. data/lib/active_support/digest.rb +5 -3
  115. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  116. data/lib/active_support/duration/iso8601_serializer.rb +9 -3
  117. data/lib/active_support/duration.rb +83 -52
  118. data/lib/active_support/encrypted_configuration.rb +72 -9
  119. data/lib/active_support/encrypted_file.rb +29 -13
  120. data/lib/active_support/environment_inquirer.rb +23 -3
  121. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  122. data/lib/active_support/error_reporter.rb +203 -0
  123. data/lib/active_support/evented_file_update_checker.rb +20 -7
  124. data/lib/active_support/execution_context/test_helper.rb +13 -0
  125. data/lib/active_support/execution_context.rb +53 -0
  126. data/lib/active_support/execution_wrapper.rb +44 -22
  127. data/lib/active_support/executor/test_helper.rb +7 -0
  128. data/lib/active_support/file_update_checker.rb +4 -2
  129. data/lib/active_support/fork_tracker.rb +28 -11
  130. data/lib/active_support/gem_version.rb +4 -4
  131. data/lib/active_support/gzip.rb +2 -0
  132. data/lib/active_support/hash_with_indifferent_access.rb +44 -19
  133. data/lib/active_support/html_safe_translation.rb +53 -0
  134. data/lib/active_support/i18n.rb +2 -1
  135. data/lib/active_support/i18n_railtie.rb +21 -14
  136. data/lib/active_support/inflector/inflections.rb +25 -7
  137. data/lib/active_support/inflector/methods.rb +50 -64
  138. data/lib/active_support/inflector/transliterate.rb +4 -2
  139. data/lib/active_support/isolated_execution_state.rb +76 -0
  140. data/lib/active_support/json/decoding.rb +2 -1
  141. data/lib/active_support/json/encoding.rb +27 -45
  142. data/lib/active_support/key_generator.rb +31 -6
  143. data/lib/active_support/lazy_load_hooks.rb +33 -7
  144. data/lib/active_support/locale/en.yml +4 -2
  145. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  146. data/lib/active_support/log_subscriber.rb +97 -35
  147. data/lib/active_support/logger.rb +9 -60
  148. data/lib/active_support/logger_thread_safe_level.rb +11 -34
  149. data/lib/active_support/message_encryptor.rb +206 -56
  150. data/lib/active_support/message_encryptors.rb +141 -0
  151. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  152. data/lib/active_support/message_pack/extensions.rb +292 -0
  153. data/lib/active_support/message_pack/serializer.rb +63 -0
  154. data/lib/active_support/message_pack.rb +50 -0
  155. data/lib/active_support/message_verifier.rb +235 -84
  156. data/lib/active_support/message_verifiers.rb +135 -0
  157. data/lib/active_support/messages/codec.rb +65 -0
  158. data/lib/active_support/messages/metadata.rb +112 -46
  159. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  160. data/lib/active_support/messages/rotator.rb +34 -32
  161. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  162. data/lib/active_support/multibyte/chars.rb +12 -11
  163. data/lib/active_support/multibyte/unicode.rb +9 -49
  164. data/lib/active_support/multibyte.rb +1 -1
  165. data/lib/active_support/notifications/fanout.rb +304 -114
  166. data/lib/active_support/notifications/instrumenter.rb +117 -35
  167. data/lib/active_support/notifications.rb +25 -25
  168. data/lib/active_support/number_helper/number_converter.rb +14 -7
  169. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  170. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  171. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -4
  172. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  173. data/lib/active_support/number_helper/number_to_rounded_converter.rb +10 -6
  174. data/lib/active_support/number_helper/rounding_helper.rb +2 -6
  175. data/lib/active_support/number_helper.rb +379 -319
  176. data/lib/active_support/option_merger.rb +10 -18
  177. data/lib/active_support/ordered_hash.rb +4 -4
  178. data/lib/active_support/ordered_options.rb +15 -1
  179. data/lib/active_support/parameter_filter.rb +105 -81
  180. data/lib/active_support/proxy_object.rb +2 -0
  181. data/lib/active_support/railtie.rb +83 -21
  182. data/lib/active_support/reloader.rb +13 -5
  183. data/lib/active_support/rescuable.rb +18 -16
  184. data/lib/active_support/ruby_features.rb +7 -0
  185. data/lib/active_support/secure_compare_rotator.rb +18 -11
  186. data/lib/active_support/security_utils.rb +1 -1
  187. data/lib/active_support/string_inquirer.rb +3 -3
  188. data/lib/active_support/subscriber.rb +11 -40
  189. data/lib/active_support/syntax_error_proxy.rb +60 -0
  190. data/lib/active_support/tagged_logging.rb +65 -25
  191. data/lib/active_support/test_case.rb +166 -27
  192. data/lib/active_support/testing/assertions.rb +61 -15
  193. data/lib/active_support/testing/autorun.rb +0 -2
  194. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  195. data/lib/active_support/testing/deprecation.rb +53 -2
  196. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  197. data/lib/active_support/testing/isolation.rb +30 -29
  198. data/lib/active_support/testing/method_call_assertions.rb +24 -11
  199. data/lib/active_support/testing/parallelization/server.rb +4 -0
  200. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  201. data/lib/active_support/testing/parallelization.rb +4 -0
  202. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  203. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  204. data/lib/active_support/testing/stream.rb +4 -6
  205. data/lib/active_support/testing/strict_warnings.rb +39 -0
  206. data/lib/active_support/testing/tagged_logging.rb +1 -1
  207. data/lib/active_support/testing/time_helpers.rb +49 -16
  208. data/lib/active_support/time_with_zone.rb +39 -28
  209. data/lib/active_support/values/time_zone.rb +50 -18
  210. data/lib/active_support/version.rb +1 -1
  211. data/lib/active_support/xml_mini/jdom.rb +4 -11
  212. data/lib/active_support/xml_mini/libxml.rb +5 -5
  213. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  214. data/lib/active_support/xml_mini/nokogiri.rb +5 -5
  215. data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
  216. data/lib/active_support/xml_mini/rexml.rb +2 -2
  217. data/lib/active_support/xml_mini.rb +7 -6
  218. data/lib/active_support.rb +28 -1
  219. metadata +150 -18
  220. data/lib/active_support/core_ext/marshal.rb +0 -26
  221. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
  222. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  223. data/lib/active_support/core_ext/uri.rb +0 -29
  224. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
  225. data/lib/active_support/per_thread_registry.rb +0 -60
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ $VERBOSE = true
4
+ Warning[:deprecated] = true
5
+
6
+ module ActiveSupport
7
+ module RaiseWarnings # :nodoc:
8
+ PROJECT_ROOT = File.expand_path("../../../../", __dir__)
9
+ ALLOWED_WARNINGS = Regexp.union(
10
+ /circular require considered harmful.*delayed_job/, # Bug in delayed job.
11
+
12
+ # Expected non-verbose warning emitted by Rails.
13
+ /Ignoring .*\.yml because it has expired/,
14
+ /Failed to validate the schema cache because/,
15
+ )
16
+
17
+ SUPPRESSED_WARNINGS = Regexp.union(
18
+ # TODO: remove if https://github.com/mikel/mail/pull/1557 or similar fix
19
+ %r{/lib/mail/parsers/.*statement not reached},
20
+ %r{/lib/mail/parsers/.*assigned but unused variable - disp_type_s},
21
+ %r{/lib/mail/parsers/.*assigned but unused variable - testEof}
22
+ )
23
+
24
+ def warn(message, *)
25
+ return if SUPPRESSED_WARNINGS.match?(message)
26
+
27
+ super
28
+
29
+ return unless message.include?(PROJECT_ROOT)
30
+ return if ALLOWED_WARNINGS.match?(message)
31
+ return unless ENV["RAILS_STRICT_WARNINGS"] || ENV["CI"]
32
+
33
+ raise message
34
+ end
35
+ ruby2_keywords :warn if respond_to?(:ruby2_keywords, true)
36
+ end
37
+ end
38
+
39
+ Warning.singleton_class.prepend(ActiveSupport::RaiseWarnings)
@@ -4,7 +4,7 @@ module ActiveSupport
4
4
  module Testing
5
5
  # Logs a "PostsControllerTest: test name" heading before each test to
6
6
  # make test.log easier to search and follow along with.
7
- module TaggedLogging #:nodoc:
7
+ module TaggedLogging # :nodoc:
8
8
  attr_writer :tagged_logger
9
9
 
10
10
  def before_setup
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "active_support/core_ext/module/redefine_method"
4
4
  require "active_support/core_ext/time/calculations"
5
- require "concurrent/map"
6
5
 
7
6
  module ActiveSupport
8
7
  module Testing
@@ -11,7 +10,7 @@ module ActiveSupport
11
10
  Stub = Struct.new(:object, :method_name, :original_method)
12
11
 
13
12
  def initialize
14
- @stubs = Concurrent::Map.new { |h, k| h[k] = {} }
13
+ @stubs = Hash.new { |h, k| h[k] = {} }
15
14
  end
16
15
 
17
16
  # Stubs object.method_name with the given block
@@ -26,7 +25,7 @@ module ActiveSupport
26
25
  unstub_object(stub)
27
26
  end
28
27
 
29
- new_name = "__simple_stub__#{method_name}"
28
+ new_name = "__simple_stub__#{method_name}__#{object_id}"
30
29
 
31
30
  @stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
32
31
 
@@ -76,6 +75,11 @@ module ActiveSupport
76
75
  # stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
77
76
  # at the end of the test.
78
77
  #
78
+ # Note that the usec for the resulting time will be set to 0 to prevent rounding
79
+ # errors with external services, like MySQL (which will round instead of floor,
80
+ # leading to off-by-one-second errors), unless the <tt>with_usec</tt> argument
81
+ # is set to <tt>true</tt>.
82
+ #
79
83
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
80
84
  # travel 1.day
81
85
  # Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
@@ -90,11 +94,11 @@ module ActiveSupport
90
94
  # User.create.created_at # => Sun, 10 Nov 2013 15:34:49 EST -05:00
91
95
  # end
92
96
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
93
- def travel(duration, &block)
94
- travel_to Time.now + duration, &block
97
+ def travel(duration, with_usec: false, &block)
98
+ travel_to Time.now + duration, with_usec: with_usec, &block
95
99
  end
96
100
 
97
- # Changes current time to the given time by stubbing +Time.now+,
101
+ # Changes current time to the given time by stubbing +Time.now+, +Time.new+,
98
102
  # +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
99
103
  # The stubs are automatically removed at the end of the test.
100
104
  #
@@ -115,7 +119,8 @@ module ActiveSupport
115
119
  #
116
120
  # Note that the usec for the time passed will be set to 0 to prevent rounding
117
121
  # errors with external services, like MySQL (which will round instead of floor,
118
- # leading to off-by-one-second errors).
122
+ # leading to off-by-one-second errors), unless the <tt>with_usec</tt> argument
123
+ # is set to <tt>true</tt>.
119
124
  #
120
125
  # This method also accepts a block, which will return the current time back to its original
121
126
  # state at the end of the block:
@@ -125,8 +130,8 @@ module ActiveSupport
125
130
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
126
131
  # end
127
132
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
128
- def travel_to(date_or_time)
129
- if block_given? && simple_stubs.stubbing(Time, :now)
133
+ def travel_to(date_or_time, with_usec: false)
134
+ if block_given? && in_block
130
135
  travel_to_nested_block_call = <<~MSG
131
136
 
132
137
  Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
@@ -156,19 +161,45 @@ module ActiveSupport
156
161
 
157
162
  if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
158
163
  now = date_or_time.midnight.to_time
164
+ elsif date_or_time.is_a?(String)
165
+ now = Time.zone.parse(date_or_time)
166
+ elsif with_usec
167
+ now = date_or_time.to_time
159
168
  else
160
169
  now = date_or_time.to_time.change(usec: 0)
161
170
  end
162
171
 
163
- simple_stubs.stub_object(Time, :now) { at(now.to_i) }
164
- simple_stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
165
- simple_stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
172
+ # +now+ must be in local system timezone, because +Time.at(now)+
173
+ # and +now.to_date+ (see stubs below) will use +now+'s timezone too!
174
+ now = now.getlocal
175
+
176
+ stubs = simple_stubs
177
+ stubbed_time = Time.now if stubs.stubbing(Time, :now)
178
+ stubs.stub_object(Time, :now) { at(now) }
179
+
180
+ stubs.stub_object(Time, :new) do |*args, **options|
181
+ if args.empty? && options.empty?
182
+ at(now)
183
+ else
184
+ stub = stubs.stubbing(Time, :new)
185
+ Time.send(stub.original_method, *args, **options)
186
+ end
187
+ end
188
+
189
+ stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
190
+ stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
166
191
 
167
192
  if block_given?
168
193
  begin
194
+ self.in_block = true
169
195
  yield
170
196
  ensure
171
- travel_back
197
+ if stubbed_time
198
+ travel_to stubbed_time
199
+ else
200
+ travel_back
201
+ end
202
+ self.in_block = false
172
203
  end
173
204
  end
174
205
  end
@@ -206,7 +237,7 @@ module ActiveSupport
206
237
  end
207
238
  alias_method :unfreeze_time, :travel_back
208
239
 
209
- # Calls +travel_to+ with +Time.now+.
240
+ # Calls +travel_to+ with +Time.now+. Forwards optional <tt>with_usec</tt> argument.
210
241
  #
211
242
  # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
212
243
  # freeze_time
@@ -222,14 +253,16 @@ module ActiveSupport
222
253
  # User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
223
254
  # end
224
255
  # Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
225
- def freeze_time(&block)
226
- travel_to Time.now, &block
256
+ def freeze_time(with_usec: false, &block)
257
+ travel_to Time.now, with_usec: with_usec, &block
227
258
  end
228
259
 
229
260
  private
230
261
  def simple_stubs
231
262
  @simple_stubs ||= SimpleStubs.new
232
263
  end
264
+
265
+ attr_accessor :in_block
233
266
  end
234
267
  end
235
268
  end
@@ -1,17 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "yaml"
4
+
3
5
  require "active_support/duration"
4
6
  require "active_support/values/time_zone"
5
7
  require "active_support/core_ext/object/acts_like"
6
8
  require "active_support/core_ext/date_and_time/compatibility"
7
9
 
8
10
  module ActiveSupport
11
+ # = Active Support \Time With Zone
12
+ #
9
13
  # A Time-like class that can represent a time in any time zone. Necessary
10
14
  # because standard Ruby Time instances are limited to UTC and the
11
15
  # system's <tt>ENV['TZ']</tt> zone.
12
16
  #
13
17
  # You shouldn't ever need to create a TimeWithZone instance directly via +new+.
14
- # Instead use methods +local+, +parse+, +at+ and +now+ on TimeZone instances,
18
+ # Instead use methods +local+, +parse+, +at+, and +now+ on TimeZone instances,
15
19
  # and +in_time_zone+ on Time and DateTime instances.
16
20
  #
17
21
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
@@ -31,18 +35,13 @@ module ActiveSupport
31
35
  # t.dst? # => true
32
36
  # t.utc_offset # => -14400
33
37
  # t.zone # => "EDT"
34
- # t.to_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400"
38
+ # t.to_fs(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400"
35
39
  # t + 1.day # => Mon, 19 May 2008 13:27:25.031505668 EDT -04:00
36
40
  # t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00.000000000 EST -05:00
37
41
  # t > Time.utc(1999) # => true
38
42
  # t.is_a?(Time) # => true
39
43
  # t.is_a?(ActiveSupport::TimeWithZone) # => true
40
44
  class TimeWithZone
41
- # Report class name as 'Time' to thwart type checking.
42
- def self.name
43
- "Time"
44
- end
45
-
46
45
  PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N" }
47
46
  PRECISIONS[0] = "%FT%T"
48
47
 
@@ -69,7 +68,7 @@ module ActiveSupport
69
68
  alias_method :getutc, :utc
70
69
  alias_method :gmtime, :utc
71
70
 
72
- # Returns the underlying TZInfo::TimezonePeriod.
71
+ # Returns the underlying +TZInfo::TimezonePeriod+.
73
72
  def period
74
73
  @period ||= time_zone.period_for_utc(@utc)
75
74
  end
@@ -172,12 +171,11 @@ module ActiveSupport
172
171
  end
173
172
  end
174
173
 
175
- def init_with(coder) #:nodoc:
174
+ def init_with(coder) # :nodoc:
176
175
  initialize(coder["utc"], coder["zone"], coder["time"])
177
176
  end
178
177
 
179
- def encode_with(coder) #:nodoc:
180
- coder.tag = "!ruby/object:ActiveSupport::TimeWithZone"
178
+ def encode_with(coder) # :nodoc:
181
179
  coder.map = { "utc" => utc, "zone" => time_zone, "time" => time }
182
180
  end
183
181
 
@@ -194,25 +192,34 @@ module ActiveSupport
194
192
  #
195
193
  # Time.zone.now.rfc2822 # => "Tue, 01 Jan 2013 04:51:39 +0000"
196
194
  def rfc2822
197
- to_s(:rfc822)
195
+ to_fs(:rfc822)
198
196
  end
199
197
  alias_method :rfc822, :rfc2822
200
198
 
201
199
  # Returns a string of the object's date and time.
200
+ def to_s
201
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
202
+ end
203
+
204
+ # Returns a string of the object's date and time.
205
+ #
206
+ # This method is aliased to <tt>to_formatted_s</tt>.
207
+ #
202
208
  # Accepts an optional <tt>format</tt>:
203
209
  # * <tt>:default</tt> - default value, mimics Ruby Time#to_s format.
204
- # * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_formatted_s(:db).
205
- # * Any key in <tt>Time::DATE_FORMATS</tt> can be used. See active_support/core_ext/time/conversions.rb.
206
- def to_s(format = :default)
210
+ # * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_fs(:db).
211
+ # * Any key in +Time::DATE_FORMATS+ can be used. See active_support/core_ext/time/conversions.rb.
212
+ def to_fs(format = :default)
207
213
  if format == :db
208
- utc.to_s(format)
214
+ utc.to_fs(format)
209
215
  elsif formatter = ::Time::DATE_FORMATS[format]
210
216
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
211
217
  else
212
- "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
218
+ # Change to to_s when deprecation is gone.
219
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}"
213
220
  end
214
221
  end
215
- alias_method :to_formatted_s, :to_s
222
+ alias_method :to_formatted_s, :to_fs
216
223
 
217
224
  # Replaces <tt>%Z</tt> directive with +zone before passing to Time#strftime,
218
225
  # so that zone information is correct.
@@ -301,9 +308,8 @@ module ActiveSupport
301
308
  alias_method :in, :+
302
309
 
303
310
  # Subtracts an interval of time and returns a new TimeWithZone object unless
304
- # the other value `acts_like?` time. Then it will return a Float of the difference
305
- # between the two times that represents the difference between the current
306
- # object's time and the +other+ time.
311
+ # the other value +acts_like?+ time. In which case, it will subtract the
312
+ # other time and return the difference in seconds as a Float.
307
313
  #
308
314
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
309
315
  # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
@@ -359,8 +365,8 @@ module ActiveSupport
359
365
  # Returns a new +ActiveSupport::TimeWithZone+ where one or more of the elements have
360
366
  # been changed according to the +options+ parameter. The time options (<tt>:hour</tt>,
361
367
  # <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly,
362
- # so if only the hour is passed, then minute, sec, usec and nsec is set to 0. If the
363
- # hour and minute is passed, then sec, usec and nsec is set to 0. The +options+
368
+ # so if only the hour is passed, then minute, sec, usec, and nsec is set to 0. If the
369
+ # hour and minute is passed, then sec, usec, and nsec is set to 0. The +options+
364
370
  # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
365
371
  # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>,
366
372
  # <tt>:nsec</tt>, <tt>:offset</tt>, <tt>:zone</tt>. Pass either <tt>:usec</tt>
@@ -440,7 +446,7 @@ module ActiveSupport
440
446
  [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
441
447
  end
442
448
 
443
- # Returns the object's date and time as a floating point number of seconds
449
+ # Returns the object's date and time as a floating-point number of seconds
444
450
  # since the Epoch (January 1, 1970 00:00 UTC).
445
451
  #
446
452
  # Time.zone.now.to_f # => 1417709320.285418
@@ -531,10 +537,10 @@ module ActiveSupport
531
537
 
532
538
  # Send the missing method to +time+ instance, and wrap result in a new
533
539
  # TimeWithZone with the existing +time_zone+.
534
- def method_missing(sym, *args, &block)
535
- wrap_with_time_zone time.__send__(sym, *args, &block)
540
+ def method_missing(...)
541
+ wrap_with_time_zone time.__send__(...)
536
542
  rescue NoMethodError => e
537
- raise e, e.message.sub(time.inspect, inspect), e.backtrace
543
+ raise e, e.message.sub(time.inspect, inspect).sub("Time", "ActiveSupport::TimeWithZone"), e.backtrace
538
544
  end
539
545
 
540
546
  private
@@ -568,7 +574,7 @@ module ActiveSupport
568
574
  end
569
575
 
570
576
  def duration_of_variable_length?(obj)
571
- ActiveSupport::Duration === obj && obj.parts.any? { |p| [:years, :months, :weeks, :days].include?(p[0]) }
577
+ ActiveSupport::Duration === obj && obj.variable?
572
578
  end
573
579
 
574
580
  def wrap_with_time_zone(time)
@@ -583,3 +589,8 @@ module ActiveSupport
583
589
  end
584
590
  end
585
591
  end
592
+
593
+ # These prevent Psych from calling `ActiveSupport::TimeWithZone.name`
594
+ # and triggering the deprecation warning about the change in Rails 7.1.
595
+ YAML.load_tags["!ruby/object:ActiveSupport::TimeWithZone"] = "ActiveSupport::TimeWithZone"
596
+ YAML.dump_tags[ActiveSupport::TimeWithZone] = "!ruby/object:ActiveSupport::TimeWithZone"
@@ -4,18 +4,20 @@ require "tzinfo"
4
4
  require "concurrent/map"
5
5
 
6
6
  module ActiveSupport
7
- # The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
7
+ # = Active Support \Time Zone
8
+ #
9
+ # The TimeZone class serves as a wrapper around +TZInfo::Timezone+ instances.
8
10
  # It allows us to do the following:
9
11
  #
10
12
  # * Limit the set of zones provided by TZInfo to a meaningful subset of 134
11
13
  # zones.
12
14
  # * Retrieve and display zones with a friendlier name
13
15
  # (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
14
- # * Lazily load TZInfo::Timezone instances only when they're needed.
16
+ # * Lazily load +TZInfo::Timezone+ instances only when they're needed.
15
17
  # * Create ActiveSupport::TimeWithZone instances via TimeZone's +local+,
16
- # +parse+, +at+ and +now+ methods.
18
+ # +parse+, +at+, and +now+ methods.
17
19
  #
18
- # If you set <tt>config.time_zone</tt> in the Rails Application, you can
20
+ # If you set <tt>config.time_zone</tt> in the \Rails Application, you can
19
21
  # access this TimeZone object via <tt>Time.zone</tt>:
20
22
  #
21
23
  # # application.rb:
@@ -27,7 +29,7 @@ module ActiveSupport
27
29
  # Time.zone.name # => "Eastern Time (US & Canada)"
28
30
  # Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00
29
31
  class TimeZone
30
- # Keys are Rails TimeZone names, values are TZInfo identifiers.
32
+ # Keys are \Rails TimeZone names, values are TZInfo identifiers.
31
33
  MAPPING = {
32
34
  "International Date Line West" => "Etc/GMT+12",
33
35
  "Midway Island" => "Pacific/Midway",
@@ -159,7 +161,7 @@ module ActiveSupport
159
161
  "Yakutsk" => "Asia/Yakutsk",
160
162
  "Darwin" => "Australia/Darwin",
161
163
  "Adelaide" => "Australia/Adelaide",
162
- "Canberra" => "Australia/Melbourne",
164
+ "Canberra" => "Australia/Canberra",
163
165
  "Melbourne" => "Australia/Melbourne",
164
166
  "Sydney" => "Australia/Sydney",
165
167
  "Brisbane" => "Australia/Brisbane",
@@ -206,7 +208,9 @@ module ActiveSupport
206
208
  TZInfo::Timezone.get(MAPPING[name] || name)
207
209
  end
208
210
 
211
+ # :stopdoc:
209
212
  alias_method :create, :new
213
+ # :startdoc:
210
214
 
211
215
  # Returns a TimeZone instance with the given name, or +nil+ if no
212
216
  # such TimeZone instance exists. (This exists to support the use of
@@ -229,12 +233,16 @@ module ActiveSupport
229
233
  # Returns +nil+ if no such time zone is known to the system.
230
234
  def [](arg)
231
235
  case arg
236
+ when self
237
+ arg
232
238
  when String
233
239
  begin
234
240
  @lazy_zones_map[arg] ||= create(arg)
235
241
  rescue TZInfo::InvalidTimezoneIdentifier
236
242
  nil
237
243
  end
244
+ when TZInfo::Timezone
245
+ @lazy_zones_map[arg.name] ||= create(arg.name, nil, arg)
238
246
  when Numeric, ActiveSupport::Duration
239
247
  arg *= 3600 if arg.abs <= 13
240
248
  all.find { |z| z.utc_offset == arg.to_i }
@@ -256,7 +264,7 @@ module ActiveSupport
256
264
  @country_zones[code] ||= load_country_zones(code)
257
265
  end
258
266
 
259
- def clear #:nodoc:
267
+ def clear # :nodoc:
260
268
  @lazy_zones_map = Concurrent::Map.new
261
269
  @country_zones = Concurrent::Map.new
262
270
  @zones = nil
@@ -290,15 +298,22 @@ module ActiveSupport
290
298
  attr_reader :name
291
299
  attr_reader :tzinfo
292
300
 
301
+ ##
302
+ # :singleton-method: create
303
+ # :call-seq: create(name, utc_offset = nil, tzinfo = nil)
304
+ #
293
305
  # Create a new TimeZone object with the given name and offset. The
294
306
  # offset is the number of seconds that this time zone is offset from UTC
295
307
  # (GMT). Seconds were chosen as the offset unit because that is the unit
296
308
  # that Ruby uses to represent time zone offsets (see Time#utc_offset).
309
+
310
+ # :stopdoc:
297
311
  def initialize(name, utc_offset = nil, tzinfo = nil)
298
312
  @name = name
299
313
  @utc_offset = utc_offset
300
314
  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
301
315
  end
316
+ # :startdoc:
302
317
 
303
318
  # Returns the offset of this time zone from UTC in seconds.
304
319
  def utc_offset
@@ -381,14 +396,28 @@ module ActiveSupport
381
396
  # If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
382
397
  # which usually returns +nil+ when given an invalid date string.
383
398
  def iso8601(str)
399
+ # Historically `Date._iso8601(nil)` returns `{}`, but in the `date` gem versions `3.2.1`, `3.1.2`, `3.0.2`,
400
+ # and `2.0.1`, `Date._iso8601(nil)` raises `TypeError` https://github.com/ruby/date/issues/39
401
+ # Future `date` releases are expected to revert back to the original behavior.
402
+ raise ArgumentError, "invalid date" if str.nil?
403
+
384
404
  parts = Date._iso8601(str)
385
405
 
386
- raise ArgumentError, "invalid date" if parts.empty?
406
+ year = parts.fetch(:year)
407
+
408
+ if parts.key?(:yday)
409
+ ordinal_date = Date.ordinal(year, parts.fetch(:yday))
410
+ month = ordinal_date.month
411
+ day = ordinal_date.day
412
+ else
413
+ month = parts.fetch(:mon)
414
+ day = parts.fetch(:mday)
415
+ end
387
416
 
388
417
  time = Time.new(
389
- parts.fetch(:year),
390
- parts.fetch(:mon),
391
- parts.fetch(:mday),
418
+ year,
419
+ month,
420
+ day,
392
421
  parts.fetch(:hour, 0),
393
422
  parts.fetch(:min, 0),
394
423
  parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
@@ -400,6 +429,9 @@ module ActiveSupport
400
429
  else
401
430
  TimeWithZone.new(nil, self, time)
402
431
  end
432
+
433
+ rescue Date::Error, KeyError
434
+ raise ArgumentError, "invalid date"
403
435
  end
404
436
 
405
437
  # Method for creating new ActiveSupport::TimeWithZone instance in time zone
@@ -508,11 +540,11 @@ module ActiveSupport
508
540
  # Time#in_time_zone() instead.
509
541
  #
510
542
  # As of tzinfo 2, utc_to_local returns a Time with a non-zero utc_offset.
511
- # See the `utc_to_local_returns_utc_offset_times` config for more info.
543
+ # See the +utc_to_local_returns_utc_offset_times+ config for more info.
512
544
  def utc_to_local(time)
513
545
  tzinfo.utc_to_local(time).yield_self do |t|
514
546
  ActiveSupport.utc_to_local_returns_utc_offset_times ?
515
- t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction)
547
+ t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction * 1_000_000)
516
548
  end
517
549
  end
518
550
 
@@ -522,27 +554,27 @@ module ActiveSupport
522
554
  tzinfo.local_to_utc(time, dst)
523
555
  end
524
556
 
525
- # Available so that TimeZone instances respond like TZInfo::Timezone
557
+ # Available so that TimeZone instances respond like +TZInfo::Timezone+
526
558
  # instances.
527
559
  def period_for_utc(time)
528
560
  tzinfo.period_for_utc(time)
529
561
  end
530
562
 
531
- # Available so that TimeZone instances respond like TZInfo::Timezone
563
+ # Available so that TimeZone instances respond like +TZInfo::Timezone+
532
564
  # instances.
533
565
  def period_for_local(time, dst = true)
534
566
  tzinfo.period_for_local(time, dst) { |periods| periods.last }
535
567
  end
536
568
 
537
- def periods_for_local(time) #:nodoc:
569
+ def periods_for_local(time) # :nodoc:
538
570
  tzinfo.periods_for_local(time)
539
571
  end
540
572
 
541
- def init_with(coder) #:nodoc:
573
+ def init_with(coder) # :nodoc:
542
574
  initialize(coder["name"])
543
575
  end
544
576
 
545
- def encode_with(coder) #:nodoc:
577
+ def encode_with(coder) # :nodoc:
546
578
  coder.tag = "!ruby/object:#{self.class}"
547
579
  coder.map = { "name" => tzinfo.name }
548
580
  end
@@ -3,7 +3,7 @@
3
3
  require_relative "gem_version"
4
4
 
5
5
  module ActiveSupport
6
- # Returns the version of the currently loaded ActiveSupport as a <tt>Gem::Version</tt>
6
+ # Returns the currently loaded version of Active Support as a +Gem::Version+.
7
7
  def self.version
8
8
  gem_version
9
9
  end
@@ -15,18 +15,11 @@ java_import org.xml.sax.Attributes unless defined? Attributes
15
15
  java_import org.w3c.dom.Node unless defined? Node
16
16
 
17
17
  module ActiveSupport
18
- module XmlMini_JDOM #:nodoc:
18
+ module XmlMini_JDOM # :nodoc:
19
19
  extend self
20
20
 
21
21
  CONTENT_KEY = "__content__"
22
22
 
23
- NODE_TYPE_NAMES = %w{ATTRIBUTE_NODE CDATA_SECTION_NODE COMMENT_NODE DOCUMENT_FRAGMENT_NODE
24
- DOCUMENT_NODE DOCUMENT_TYPE_NODE ELEMENT_NODE ENTITY_NODE ENTITY_REFERENCE_NODE NOTATION_NODE
25
- PROCESSING_INSTRUCTION_NODE TEXT_NODE}
26
-
27
- node_type_map = {}
28
- NODE_TYPE_NAMES.each { |type| node_type_map[Node.send(type)] = type }
29
-
30
23
  # Parse an XML Document string or IO into a simple hash using Java's jdom.
31
24
  # data::
32
25
  # XML Document string or IO to parse
@@ -80,7 +73,7 @@ module ActiveSupport
80
73
  if child_nodes.length > 0
81
74
  (0...child_nodes.length).each do |i|
82
75
  child = child_nodes.item(i)
83
- merge_element!(hash, child, depth - 1) unless child.node_type == Node.TEXT_NODE
76
+ merge_element!(hash, child, depth - 1) unless child.node_type == Node::TEXT_NODE
84
77
  end
85
78
  merge_texts!(hash, element) unless empty_content?(element)
86
79
  hash
@@ -156,7 +149,7 @@ module ActiveSupport
156
149
  child_nodes = element.child_nodes
157
150
  (0...child_nodes.length).each do |i|
158
151
  item = child_nodes.item(i)
159
- if item.node_type == Node.TEXT_NODE
152
+ if item.node_type == Node::TEXT_NODE
160
153
  texts << item.get_data
161
154
  end
162
155
  end
@@ -172,7 +165,7 @@ module ActiveSupport
172
165
  child_nodes = element.child_nodes
173
166
  (0...child_nodes.length).each do |i|
174
167
  item = child_nodes.item(i)
175
- if item.node_type == Node.TEXT_NODE
168
+ if item.node_type == Node::TEXT_NODE
176
169
  text << item.get_data.strip
177
170
  end
178
171
  end
@@ -5,7 +5,7 @@ require "active_support/core_ext/object/blank"
5
5
  require "stringio"
6
6
 
7
7
  module ActiveSupport
8
- module XmlMini_LibXML #:nodoc:
8
+ module XmlMini_LibXML # :nodoc:
9
9
  extend self
10
10
 
11
11
  # Parse an XML Document string or IO into a simple hash using libxml.
@@ -25,15 +25,15 @@ module ActiveSupport
25
25
  end
26
26
  end
27
27
 
28
- module LibXML #:nodoc:
29
- module Conversions #:nodoc:
30
- module Document #:nodoc:
28
+ module LibXML # :nodoc:
29
+ module Conversions # :nodoc:
30
+ module Document # :nodoc:
31
31
  def to_hash
32
32
  root.to_hash
33
33
  end
34
34
  end
35
35
 
36
- module Node #:nodoc:
36
+ module Node # :nodoc:
37
37
  CONTENT_ROOT = "__content__"
38
38
 
39
39
  # Convert XML document to hash.
@@ -5,7 +5,7 @@ require "active_support/core_ext/object/blank"
5
5
  require "stringio"
6
6
 
7
7
  module ActiveSupport
8
- module XmlMini_LibXMLSAX #:nodoc:
8
+ module XmlMini_LibXMLSAX # :nodoc:
9
9
  extend self
10
10
 
11
11
  # Class that will build the hash while the XML document