activesupport 6.1.7.2 → 7.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (222) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +866 -411
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  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 +27 -7
  8. data/lib/active_support/benchmarkable.rb +3 -2
  9. data/lib/active_support/broadcast_logger.rb +250 -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 +52 -19
  14. data/lib/active_support/cache/mem_cache_store.rb +195 -60
  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 +478 -247
  21. data/lib/active_support/callbacks.rb +227 -105
  22. data/lib/active_support/code_generator.rb +65 -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 +1 -1
  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 -14
  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 +41 -18
  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 +15 -4
  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 +40 -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 -193
  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 +29 -10
  94. data/lib/active_support/core_ext/time/conversions.rb +14 -13
  95. data/lib/active_support/core_ext/time/zones.rb +12 -28
  96. data/lib/active_support/core_ext.rb +1 -0
  97. data/lib/active_support/current_attributes.rb +46 -21
  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 +42 -25
  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 +4 -4
  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 +79 -49
  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 +31 -12
  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 -13
  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 +38 -18
  133. data/lib/active_support/html_safe_translation.rb +43 -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 -63
  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 +3 -1
  145. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  146. data/lib/active_support/log_subscriber.rb +96 -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 +109 -35
  167. data/lib/active_support/notifications.rb +24 -24
  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/rounding_helper.rb +1 -5
  174. data/lib/active_support/number_helper.rb +379 -319
  175. data/lib/active_support/option_merger.rb +10 -18
  176. data/lib/active_support/ordered_hash.rb +4 -4
  177. data/lib/active_support/ordered_options.rb +15 -1
  178. data/lib/active_support/parameter_filter.rb +104 -80
  179. data/lib/active_support/proxy_object.rb +2 -0
  180. data/lib/active_support/railtie.rb +83 -21
  181. data/lib/active_support/reloader.rb +12 -4
  182. data/lib/active_support/rescuable.rb +14 -12
  183. data/lib/active_support/ruby_features.rb +7 -0
  184. data/lib/active_support/secure_compare_rotator.rb +18 -11
  185. data/lib/active_support/string_inquirer.rb +3 -3
  186. data/lib/active_support/subscriber.rb +11 -40
  187. data/lib/active_support/syntax_error_proxy.rb +70 -0
  188. data/lib/active_support/tagged_logging.rb +60 -24
  189. data/lib/active_support/test_case.rb +166 -27
  190. data/lib/active_support/testing/assertions.rb +60 -14
  191. data/lib/active_support/testing/autorun.rb +0 -2
  192. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  193. data/lib/active_support/testing/deprecation.rb +53 -2
  194. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  195. data/lib/active_support/testing/isolation.rb +30 -29
  196. data/lib/active_support/testing/method_call_assertions.rb +24 -11
  197. data/lib/active_support/testing/parallelization/server.rb +4 -0
  198. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  199. data/lib/active_support/testing/parallelization.rb +4 -0
  200. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  201. data/lib/active_support/testing/stream.rb +4 -6
  202. data/lib/active_support/testing/strict_warnings.rb +39 -0
  203. data/lib/active_support/testing/tagged_logging.rb +1 -1
  204. data/lib/active_support/testing/time_helpers.rb +49 -16
  205. data/lib/active_support/time_with_zone.rb +39 -28
  206. data/lib/active_support/values/time_zone.rb +38 -17
  207. data/lib/active_support/version.rb +1 -1
  208. data/lib/active_support/xml_mini/jdom.rb +4 -11
  209. data/lib/active_support/xml_mini/libxml.rb +5 -5
  210. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  211. data/lib/active_support/xml_mini/nokogiri.rb +5 -5
  212. data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
  213. data/lib/active_support/xml_mini/rexml.rb +2 -2
  214. data/lib/active_support/xml_mini.rb +7 -6
  215. data/lib/active_support.rb +28 -1
  216. metadata +107 -18
  217. data/lib/active_support/core_ext/marshal.rb +0 -26
  218. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
  219. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  220. data/lib/active_support/core_ext/uri.rb +0 -29
  221. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
  222. data/lib/active_support/per_thread_registry.rb +0 -61
@@ -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",
@@ -229,12 +231,16 @@ module ActiveSupport
229
231
  # Returns +nil+ if no such time zone is known to the system.
230
232
  def [](arg)
231
233
  case arg
234
+ when self
235
+ arg
232
236
  when String
233
237
  begin
234
238
  @lazy_zones_map[arg] ||= create(arg)
235
239
  rescue TZInfo::InvalidTimezoneIdentifier
236
240
  nil
237
241
  end
242
+ when TZInfo::Timezone
243
+ @lazy_zones_map[arg.name] ||= create(arg.name, nil, arg)
238
244
  when Numeric, ActiveSupport::Duration
239
245
  arg *= 3600 if arg.abs <= 13
240
246
  all.find { |z| z.utc_offset == arg.to_i }
@@ -256,7 +262,7 @@ module ActiveSupport
256
262
  @country_zones[code] ||= load_country_zones(code)
257
263
  end
258
264
 
259
- def clear #:nodoc:
265
+ def clear # :nodoc:
260
266
  @lazy_zones_map = Concurrent::Map.new
261
267
  @country_zones = Concurrent::Map.new
262
268
  @zones = nil
@@ -381,16 +387,28 @@ module ActiveSupport
381
387
  # If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
382
388
  # which usually returns +nil+ when given an invalid date string.
383
389
  def iso8601(str)
390
+ # Historically `Date._iso8601(nil)` returns `{}`, but in the `date` gem versions `3.2.1`, `3.1.2`, `3.0.2`,
391
+ # and `2.0.1`, `Date._iso8601(nil)` raises `TypeError` https://github.com/ruby/date/issues/39
392
+ # Future `date` releases are expected to revert back to the original behavior.
384
393
  raise ArgumentError, "invalid date" if str.nil?
385
394
 
386
395
  parts = Date._iso8601(str)
387
396
 
388
- raise ArgumentError, "invalid date" if parts.empty?
397
+ year = parts.fetch(:year)
398
+
399
+ if parts.key?(:yday)
400
+ ordinal_date = Date.ordinal(year, parts.fetch(:yday))
401
+ month = ordinal_date.month
402
+ day = ordinal_date.day
403
+ else
404
+ month = parts.fetch(:mon)
405
+ day = parts.fetch(:mday)
406
+ end
389
407
 
390
408
  time = Time.new(
391
- parts.fetch(:year),
392
- parts.fetch(:mon),
393
- parts.fetch(:mday),
409
+ year,
410
+ month,
411
+ day,
394
412
  parts.fetch(:hour, 0),
395
413
  parts.fetch(:min, 0),
396
414
  parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
@@ -402,6 +420,9 @@ module ActiveSupport
402
420
  else
403
421
  TimeWithZone.new(nil, self, time)
404
422
  end
423
+
424
+ rescue Date::Error, KeyError
425
+ raise ArgumentError, "invalid date"
405
426
  end
406
427
 
407
428
  # Method for creating new ActiveSupport::TimeWithZone instance in time zone
@@ -514,7 +535,7 @@ module ActiveSupport
514
535
  def utc_to_local(time)
515
536
  tzinfo.utc_to_local(time).yield_self do |t|
516
537
  ActiveSupport.utc_to_local_returns_utc_offset_times ?
517
- t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction)
538
+ t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction * 1_000_000)
518
539
  end
519
540
  end
520
541
 
@@ -524,27 +545,27 @@ module ActiveSupport
524
545
  tzinfo.local_to_utc(time, dst)
525
546
  end
526
547
 
527
- # Available so that TimeZone instances respond like TZInfo::Timezone
548
+ # Available so that TimeZone instances respond like +TZInfo::Timezone+
528
549
  # instances.
529
550
  def period_for_utc(time)
530
551
  tzinfo.period_for_utc(time)
531
552
  end
532
553
 
533
- # Available so that TimeZone instances respond like TZInfo::Timezone
554
+ # Available so that TimeZone instances respond like +TZInfo::Timezone+
534
555
  # instances.
535
556
  def period_for_local(time, dst = true)
536
557
  tzinfo.period_for_local(time, dst) { |periods| periods.last }
537
558
  end
538
559
 
539
- def periods_for_local(time) #:nodoc:
560
+ def periods_for_local(time) # :nodoc:
540
561
  tzinfo.periods_for_local(time)
541
562
  end
542
563
 
543
- def init_with(coder) #:nodoc:
564
+ def init_with(coder) # :nodoc:
544
565
  initialize(coder["name"])
545
566
  end
546
567
 
547
- def encode_with(coder) #:nodoc:
568
+ def encode_with(coder) # :nodoc:
548
569
  coder.tag = "!ruby/object:#{self.class}"
549
570
  coder.map = { "name" => tzinfo.name }
550
571
  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
@@ -3,14 +3,14 @@
3
3
  begin
4
4
  require "nokogiri"
5
5
  rescue LoadError => e
6
- $stderr.puts "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
6
+ warn "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
7
7
  raise e
8
8
  end
9
9
  require "active_support/core_ext/object/blank"
10
10
  require "stringio"
11
11
 
12
12
  module ActiveSupport
13
- module XmlMini_Nokogiri #:nodoc:
13
+ module XmlMini_Nokogiri # :nodoc:
14
14
  extend self
15
15
 
16
16
  # Parse an XML Document string or IO into a simple hash using libxml / nokogiri.
@@ -30,14 +30,14 @@ module ActiveSupport
30
30
  end
31
31
  end
32
32
 
33
- module Conversions #:nodoc:
34
- module Document #:nodoc:
33
+ module Conversions # :nodoc:
34
+ module Document # :nodoc:
35
35
  def to_hash
36
36
  root.to_hash
37
37
  end
38
38
  end
39
39
 
40
- module Node #:nodoc:
40
+ module Node # :nodoc:
41
41
  CONTENT_ROOT = "__content__"
42
42
 
43
43
  # Convert XML document to hash.
@@ -3,14 +3,14 @@
3
3
  begin
4
4
  require "nokogiri"
5
5
  rescue LoadError => e
6
- $stderr.puts "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
6
+ warn "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
7
7
  raise e
8
8
  end
9
9
  require "active_support/core_ext/object/blank"
10
10
  require "stringio"
11
11
 
12
12
  module ActiveSupport
13
- module XmlMini_NokogiriSAX #:nodoc:
13
+ module XmlMini_NokogiriSAX # :nodoc:
14
14
  extend self
15
15
 
16
16
  # Class that will build the hash while the XML document