activesupport 4.2.11.1 → 6.0.3.1

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

Potentially problematic release.


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

Files changed (263) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -411
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +58 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +95 -91
  13. data/lib/active_support/cache/memory_store.rb +39 -36
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +75 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +331 -217
  19. data/lib/active_support/callbacks.rb +650 -592
  20. data/lib/active_support/concern.rb +35 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +13 -14
  24. data/lib/active_support/core_ext/array/access.rb +41 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  29. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
  31. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +45 -31
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +114 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/compact.rb +4 -23
  61. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  64. data/lib/active_support/core_ext/hash/except.rb +12 -9
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  66. data/lib/active_support/core_ext/hash/keys.rb +19 -42
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  68. data/lib/active_support/core_ext/hash/slice.rb +5 -27
  69. data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
  70. data/lib/active_support/core_ext/hash.rb +10 -9
  71. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  72. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  73. data/lib/active_support/core_ext/integer/time.rb +11 -18
  74. data/lib/active_support/core_ext/integer.rb +5 -3
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/kernel.rb +5 -5
  79. data/lib/active_support/core_ext/load_error.rb +3 -22
  80. data/lib/active_support/core_ext/marshal.rb +8 -8
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +133 -30
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +44 -19
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -7
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -11
  94. data/lib/active_support/core_ext/name_error.rb +22 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  99. data/lib/active_support/core_ext/numeric.rb +5 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +27 -3
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +13 -93
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +51 -20
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  110. data/lib/active_support/core_ext/object/try.rb +81 -23
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/object.rb +14 -13
  113. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  115. data/lib/active_support/core_ext/range/each.rb +18 -17
  116. data/lib/active_support/core_ext/range/include_range.rb +7 -21
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/range.rb +7 -4
  120. data/lib/active_support/core_ext/regexp.rb +2 -0
  121. data/lib/active_support/core_ext/securerandom.rb +45 -0
  122. data/lib/active_support/core_ext/string/access.rb +16 -6
  123. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  124. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +48 -6
  127. data/lib/active_support/core_ext/string/indent.rb +6 -4
  128. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  129. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  130. data/lib/active_support/core_ext/string/multibyte.rb +16 -7
  131. data/lib/active_support/core_ext/string/output_safety.rb +93 -40
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +6 -5
  134. data/lib/active_support/core_ext/string/zones.rb +4 -2
  135. data/lib/active_support/core_ext/string.rb +15 -13
  136. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  137. data/lib/active_support/core_ext/time/calculations.rb +115 -52
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  140. data/lib/active_support/core_ext/time/zones.rb +41 -7
  141. data/lib/active_support/core_ext/time.rb +7 -6
  142. data/lib/active_support/core_ext/uri.rb +6 -7
  143. data/lib/active_support/core_ext.rb +3 -1
  144. data/lib/active_support/current_attributes.rb +203 -0
  145. data/lib/active_support/dependencies/autoload.rb +2 -0
  146. data/lib/active_support/dependencies/interlock.rb +57 -0
  147. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  148. data/lib/active_support/dependencies.rb +208 -166
  149. data/lib/active_support/deprecation/behaviors.rb +44 -11
  150. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  151. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  152. data/lib/active_support/deprecation/method_wrappers.rb +61 -21
  153. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  154. data/lib/active_support/deprecation/reporting.rb +32 -12
  155. data/lib/active_support/deprecation.rb +12 -9
  156. data/lib/active_support/descendants_tracker.rb +57 -9
  157. data/lib/active_support/digest.rb +20 -0
  158. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  159. data/lib/active_support/duration/iso8601_serializer.rb +53 -0
  160. data/lib/active_support/duration.rb +315 -40
  161. data/lib/active_support/encrypted_configuration.rb +45 -0
  162. data/lib/active_support/encrypted_file.rb +100 -0
  163. data/lib/active_support/evented_file_update_checker.rb +234 -0
  164. data/lib/active_support/execution_wrapper.rb +129 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/gem_version.rb +6 -4
  168. data/lib/active_support/gzip.rb +7 -5
  169. data/lib/active_support/hash_with_indifferent_access.rb +129 -30
  170. data/lib/active_support/i18n.rb +9 -6
  171. data/lib/active_support/i18n_railtie.rb +50 -14
  172. data/lib/active_support/inflections.rb +13 -11
  173. data/lib/active_support/inflector/inflections.rb +58 -13
  174. data/lib/active_support/inflector/methods.rb +159 -145
  175. data/lib/active_support/inflector/transliterate.rb +84 -34
  176. data/lib/active_support/inflector.rb +7 -5
  177. data/lib/active_support/json/decoding.rb +32 -30
  178. data/lib/active_support/json/encoding.rb +17 -60
  179. data/lib/active_support/json.rb +4 -2
  180. data/lib/active_support/key_generator.rb +11 -43
  181. data/lib/active_support/lazy_load_hooks.rb +53 -20
  182. data/lib/active_support/locale/en.rb +33 -0
  183. data/lib/active_support/locale/en.yml +2 -0
  184. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  185. data/lib/active_support/log_subscriber.rb +44 -19
  186. data/lib/active_support/logger.rb +9 -23
  187. data/lib/active_support/logger_silence.rb +32 -14
  188. data/lib/active_support/logger_thread_safe_level.rb +32 -8
  189. data/lib/active_support/message_encryptor.rb +166 -53
  190. data/lib/active_support/message_verifier.rb +149 -16
  191. data/lib/active_support/messages/metadata.rb +72 -0
  192. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  193. data/lib/active_support/messages/rotator.rb +56 -0
  194. data/lib/active_support/multibyte/chars.rb +56 -63
  195. data/lib/active_support/multibyte/unicode.rb +56 -290
  196. data/lib/active_support/multibyte.rb +4 -2
  197. data/lib/active_support/notifications/fanout.rb +109 -22
  198. data/lib/active_support/notifications/instrumenter.rb +107 -16
  199. data/lib/active_support/notifications.rb +51 -10
  200. data/lib/active_support/number_helper/number_converter.rb +16 -15
  201. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
  202. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  203. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
  204. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
  205. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  206. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  207. data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
  208. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  209. data/lib/active_support/number_helper.rb +105 -68
  210. data/lib/active_support/option_merger.rb +24 -4
  211. data/lib/active_support/ordered_hash.rb +7 -5
  212. data/lib/active_support/ordered_options.rb +27 -5
  213. data/lib/active_support/parameter_filter.rb +128 -0
  214. data/lib/active_support/per_thread_registry.rb +9 -4
  215. data/lib/active_support/proxy_object.rb +2 -0
  216. data/lib/active_support/rails.rb +10 -8
  217. data/lib/active_support/railtie.rb +43 -9
  218. data/lib/active_support/reloader.rb +130 -0
  219. data/lib/active_support/rescuable.rb +108 -53
  220. data/lib/active_support/security_utils.rb +15 -11
  221. data/lib/active_support/string_inquirer.rb +11 -4
  222. data/lib/active_support/subscriber.rb +74 -30
  223. data/lib/active_support/tagged_logging.rb +25 -13
  224. data/lib/active_support/test_case.rb +107 -44
  225. data/lib/active_support/testing/assertions.rb +151 -20
  226. data/lib/active_support/testing/autorun.rb +4 -2
  227. data/lib/active_support/testing/constant_lookup.rb +2 -1
  228. data/lib/active_support/testing/declarative.rb +3 -1
  229. data/lib/active_support/testing/deprecation.rb +13 -10
  230. data/lib/active_support/testing/file_fixtures.rb +38 -0
  231. data/lib/active_support/testing/isolation.rb +35 -26
  232. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  233. data/lib/active_support/testing/parallelization.rb +134 -0
  234. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  235. data/lib/active_support/testing/stream.rb +43 -0
  236. data/lib/active_support/testing/tagged_logging.rb +3 -1
  237. data/lib/active_support/testing/time_helpers.rb +84 -20
  238. data/lib/active_support/time.rb +14 -12
  239. data/lib/active_support/time_with_zone.rb +179 -39
  240. data/lib/active_support/values/time_zone.rb +203 -63
  241. data/lib/active_support/version.rb +3 -1
  242. data/lib/active_support/xml_mini/jdom.rb +116 -115
  243. data/lib/active_support/xml_mini/libxml.rb +16 -13
  244. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  245. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  246. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  247. data/lib/active_support/xml_mini/rexml.rb +11 -9
  248. data/lib/active_support/xml_mini.rb +38 -46
  249. data/lib/active_support.rb +13 -11
  250. metadata +84 -26
  251. data/lib/active_support/concurrency/latch.rb +0 -27
  252. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  253. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  254. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  255. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  256. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  257. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  258. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  259. data/lib/active_support/core_ext/object/itself.rb +0 -15
  260. data/lib/active_support/core_ext/struct.rb +0 -6
  261. data/lib/active_support/core_ext/thread.rb +0 -86
  262. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  263. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,48 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/redefine_method"
4
+ require "active_support/core_ext/time/calculations"
5
+ require "concurrent/map"
6
+
1
7
  module ActiveSupport
2
8
  module Testing
3
9
  class SimpleStubs # :nodoc:
4
10
  Stub = Struct.new(:object, :method_name, :original_method)
5
11
 
6
12
  def initialize
7
- @stubs = {}
13
+ @stubs = Concurrent::Map.new { |h, k| h[k] = {} }
8
14
  end
9
15
 
10
16
  def stub_object(object, method_name, &block)
11
- key = [object.object_id, method_name]
12
-
13
- if stub = @stubs[key]
17
+ if stub = stubbing(object, method_name)
14
18
  unstub_object(stub)
15
19
  end
16
20
 
17
21
  new_name = "__simple_stub__#{method_name}"
18
22
 
19
- @stubs[key] = Stub.new(object, method_name, new_name)
23
+ @stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
20
24
 
21
- object.singleton_class.send :alias_method, new_name, method_name
25
+ object.singleton_class.alias_method new_name, method_name
22
26
  object.define_singleton_method(method_name, &block)
23
27
  end
24
28
 
25
29
  def unstub_all!
26
- @stubs.each_value do |stub|
27
- unstub_object(stub)
30
+ @stubs.each_value do |object_stubs|
31
+ object_stubs.each_value do |stub|
32
+ unstub_object(stub)
33
+ end
28
34
  end
29
- @stubs = {}
35
+ @stubs.clear
30
36
  end
31
37
 
32
- private
38
+ def stubbing(object, method_name)
39
+ @stubs[object.object_id][method_name]
40
+ end
33
41
 
42
+ private
34
43
  def unstub_object(stub)
35
44
  singleton_class = stub.object.singleton_class
36
- singleton_class.send :undef_method, stub.method_name
37
- singleton_class.send :alias_method, stub.method_name, stub.original_method
38
- singleton_class.send :undef_method, stub.original_method
45
+ singleton_class.silence_redefinition_of_method stub.method_name
46
+ singleton_class.alias_method stub.method_name, stub.original_method
47
+ singleton_class.undef_method stub.original_method
39
48
  end
40
49
  end
41
50
 
42
- # Containing helpers that helps you test passage of time.
51
+ # Contains helpers that help you test passage of time.
43
52
  module TimeHelpers
53
+ def after_teardown
54
+ travel_back
55
+ super
56
+ end
57
+
44
58
  # Changes current time to the time in the future or in the past by a given time difference by
45
- # stubbing +Time.now+, +Date.today+, and +DateTime.now+.
59
+ # stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
60
+ # at the end of the test.
46
61
  #
47
62
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
48
63
  # travel 1.day
@@ -64,9 +79,10 @@ module ActiveSupport
64
79
 
65
80
  # Changes current time to the given time by stubbing +Time.now+,
66
81
  # +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
82
+ # The stubs are automatically removed at the end of the test.
67
83
  #
68
84
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
69
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
85
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
70
86
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
71
87
  # Date.current # => Wed, 24 Nov 2004
72
88
  # DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
@@ -88,11 +104,39 @@ module ActiveSupport
88
104
  # state at the end of the block:
89
105
  #
90
106
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
91
- # travel_to Time.new(2004, 11, 24, 01, 04, 44) do
107
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44) do
92
108
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
93
109
  # end
94
110
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
95
111
  def travel_to(date_or_time)
112
+ if block_given? && simple_stubs.stubbing(Time, :now)
113
+ travel_to_nested_block_call = <<~MSG
114
+
115
+ Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
116
+
117
+ Instead of:
118
+
119
+ travel_to 2.days.from_now do
120
+ # 2 days from today
121
+ travel_to 3.days.from_now do
122
+ # 5 days from today
123
+ end
124
+ end
125
+
126
+ preferred way to achieve above is:
127
+
128
+ travel 2.days do
129
+ # 2 days from today
130
+ end
131
+
132
+ travel 5.days do
133
+ # 5 days from today
134
+ end
135
+
136
+ MSG
137
+ raise travel_to_nested_block_call
138
+ end
139
+
96
140
  if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
97
141
  now = date_or_time.midnight.to_time
98
142
  else
@@ -113,19 +157,39 @@ module ActiveSupport
113
157
  end
114
158
 
115
159
  # Returns the current time back to its original state, by removing the stubs added by
116
- # `travel` and `travel_to`.
160
+ # +travel+, +travel_to+, and +freeze_time+.
117
161
  #
118
162
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
119
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
163
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
120
164
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
121
165
  # travel_back
122
166
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
123
167
  def travel_back
124
168
  simple_stubs.unstub_all!
125
169
  end
170
+ alias_method :unfreeze_time, :travel_back
126
171
 
127
- private
172
+ # Calls +travel_to+ with +Time.now+.
173
+ #
174
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
175
+ # freeze_time
176
+ # sleep(1)
177
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
178
+ #
179
+ # This method also accepts a block, which will return the current time back to its original
180
+ # state at the end of the block:
181
+ #
182
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
183
+ # freeze_time do
184
+ # sleep(1)
185
+ # User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
186
+ # end
187
+ # Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
188
+ def freeze_time(&block)
189
+ travel_to Time.now, &block
190
+ end
128
191
 
192
+ private
129
193
  def simple_stubs
130
194
  @simple_stubs ||= SimpleStubs.new
131
195
  end
@@ -1,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
- autoload :Duration, 'active_support/duration'
3
- autoload :TimeWithZone, 'active_support/time_with_zone'
4
- autoload :TimeZone, 'active_support/values/time_zone'
4
+ autoload :Duration, "active_support/duration"
5
+ autoload :TimeWithZone, "active_support/time_with_zone"
6
+ autoload :TimeZone, "active_support/values/time_zone"
5
7
  end
6
8
 
7
- require 'date'
8
- require 'time'
9
+ require "date"
10
+ require "time"
9
11
 
10
- require 'active_support/core_ext/time'
11
- require 'active_support/core_ext/date'
12
- require 'active_support/core_ext/date_time'
12
+ require "active_support/core_ext/time"
13
+ require "active_support/core_ext/date"
14
+ require "active_support/core_ext/date_time"
13
15
 
14
- require 'active_support/core_ext/integer/time'
15
- require 'active_support/core_ext/numeric/time'
16
+ require "active_support/core_ext/integer/time"
17
+ require "active_support/core_ext/numeric/time"
16
18
 
17
- require 'active_support/core_ext/string/conversions'
18
- require 'active_support/core_ext/string/zones'
19
+ require "active_support/core_ext/string/conversions"
20
+ require "active_support/core_ext/string/zones"
@@ -1,6 +1,9 @@
1
- require 'active_support/values/time_zone'
2
- require 'active_support/core_ext/object/acts_like'
3
- require 'active_support/core_ext/date_and_time/compatibility'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/duration"
4
+ require "active_support/values/time_zone"
5
+ require "active_support/core_ext/object/acts_like"
6
+ require "active_support/core_ext/date_and_time/compatibility"
4
7
 
5
8
  module ActiveSupport
6
9
  # A Time-like class that can represent a time in any time zone. Necessary
@@ -14,7 +17,7 @@ module ActiveSupport
14
17
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
15
18
  # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
16
19
  # Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
17
- # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
20
+ # Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
18
21
  # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
19
22
  # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
20
23
  #
@@ -35,12 +38,14 @@ module ActiveSupport
35
38
  # t.is_a?(Time) # => true
36
39
  # t.is_a?(ActiveSupport::TimeWithZone) # => true
37
40
  class TimeWithZone
38
-
39
41
  # Report class name as 'Time' to thwart type checking.
40
42
  def self.name
41
- 'Time'
43
+ "Time"
42
44
  end
43
45
 
46
+ PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N" }
47
+ PRECISIONS[0] = "%FT%T"
48
+
44
49
  include Comparable, DateAndTime::Compatibility
45
50
  attr_reader :time_zone
46
51
 
@@ -99,7 +104,7 @@ module ActiveSupport
99
104
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
100
105
  # Time.zone.now.utc? # => false
101
106
  def utc?
102
- time_zone.name == 'UTC'
107
+ period.offset.abbreviation == :UTC || period.offset.abbreviation == :UCT
103
108
  end
104
109
  alias_method :gmt?, :utc?
105
110
 
@@ -122,24 +127,30 @@ module ActiveSupport
122
127
  utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
123
128
  end
124
129
 
125
- # Time uses +zone+ to display the time zone abbreviation, so we're
126
- # duck-typing it.
130
+ # Returns the time zone abbreviation.
131
+ #
132
+ # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
133
+ # Time.zone.now.zone # => "EST"
127
134
  def zone
128
135
  period.zone_identifier.to_s
129
136
  end
130
137
 
138
+ # Returns a string of the object's date, time, zone, and offset from UTC.
139
+ #
140
+ # Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
131
141
  def inspect
132
142
  "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
133
143
  end
134
144
 
145
+ # Returns a string of the object's date and time in the ISO 8601 standard
146
+ # format.
147
+ #
148
+ # Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00"
135
149
  def xmlschema(fraction_digits = 0)
136
- fraction = if fraction_digits.to_i > 0
137
- (".%06i" % time.usec)[0, fraction_digits.to_i + 1]
138
- end
139
-
140
- "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}#{formatted_offset(true, 'Z')}"
150
+ "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z')}"
141
151
  end
142
152
  alias_method :iso8601, :xmlschema
153
+ alias_method :rfc3339, :xmlschema
143
154
 
144
155
  # Coerces time to a string for JSON encoding. The default format is ISO 8601.
145
156
  # You can get %Y/%m/%d %H:%M:%S +offset style by setting
@@ -162,15 +173,12 @@ module ActiveSupport
162
173
  end
163
174
 
164
175
  def init_with(coder) #:nodoc:
165
- initialize(coder['utc'], coder['zone'], coder['time'])
176
+ initialize(coder["utc"], coder["zone"], coder["time"])
166
177
  end
167
178
 
168
179
  def encode_with(coder) #:nodoc:
169
- if coder.respond_to?(:represent_object)
170
- coder.represent_object(nil, utc)
171
- else
172
- coder.represent_scalar(nil, utc.strftime("%Y-%m-%d %H:%M:%S.%9NZ"))
173
- end
180
+ coder.tag = "!ruby/object:ActiveSupport::TimeWithZone"
181
+ coder.map = { "utc" => utc, "zone" => time_zone, "time" => time }
174
182
  end
175
183
 
176
184
  # Returns a string of the object's date and time in the format used by
@@ -192,7 +200,7 @@ module ActiveSupport
192
200
 
193
201
  # Returns a string of the object's date and time.
194
202
  # Accepts an optional <tt>format</tt>:
195
- # * <tt>:default</tt> - default value, mimics Ruby 1.9 Time#to_s format.
203
+ # * <tt>:default</tt> - default value, mimics Ruby Time#to_s format.
196
204
  # * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_formatted_s(:db).
197
205
  # * Any key in <tt>Time::DATE_FORMATS</tt> can be used. See active_support/core_ext/time/conversions.rb.
198
206
  def to_s(format = :default)
@@ -201,7 +209,7 @@ module ActiveSupport
201
209
  elsif formatter = ::Time::DATE_FORMATS[format]
202
210
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
203
211
  else
204
- "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby 1.9 Time#to_s format
212
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
205
213
  end
206
214
  end
207
215
  alias_method :to_formatted_s, :to_s
@@ -217,6 +225,8 @@ module ActiveSupport
217
225
  def <=>(other)
218
226
  utc <=> other
219
227
  end
228
+ alias_method :before?, :<
229
+ alias_method :after?, :>
220
230
 
221
231
  # Returns true if the current object's time is within the specified
222
232
  # +min+ and +max+ time.
@@ -240,6 +250,7 @@ module ActiveSupport
240
250
  utc.future?
241
251
  end
242
252
 
253
+ # Returns +true+ if +other+ is equal to current object.
243
254
  def eql?(other)
244
255
  other.eql?(utc)
245
256
  end
@@ -248,9 +259,23 @@ module ActiveSupport
248
259
  utc.hash
249
260
  end
250
261
 
262
+ # Adds an interval of time to the current object's time and returns that
263
+ # value as a new TimeWithZone object.
264
+ #
265
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
266
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
267
+ # now + 1000 # => Sun, 02 Nov 2014 01:43:08 EDT -04:00
268
+ #
269
+ # If we're adding a Duration of variable length (i.e., years, months, days),
270
+ # move forward from #time, otherwise move forward from #utc, for accuracy
271
+ # when moving across DST boundaries.
272
+ #
273
+ # For instance, a time + 24.hours will advance exactly 24 hours, while a
274
+ # time + 1.day will advance 23-25 hours, depending on the day.
275
+ #
276
+ # now + 24.hours # => Mon, 03 Nov 2014 00:26:28 EST -05:00
277
+ # now + 1.day # => Mon, 03 Nov 2014 01:26:28 EST -05:00
251
278
  def +(other)
252
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
253
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
254
279
  if duration_of_variable_length?(other)
255
280
  method_missing(:+, other)
256
281
  else
@@ -258,10 +283,34 @@ module ActiveSupport
258
283
  result.in_time_zone(time_zone)
259
284
  end
260
285
  end
286
+ alias_method :since, :+
287
+ alias_method :in, :+
261
288
 
289
+ # Subtracts an interval of time and returns a new TimeWithZone object unless
290
+ # the other value `acts_like?` time. Then it will return a Float of the difference
291
+ # between the two times that represents the difference between the current
292
+ # object's time and the +other+ time.
293
+ #
294
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
295
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
296
+ # now - 1000 # => Mon, 03 Nov 2014 00:09:48 EST -05:00
297
+ #
298
+ # If subtracting a Duration of variable length (i.e., years, months, days),
299
+ # move backward from #time, otherwise move backward from #utc, for accuracy
300
+ # when moving across DST boundaries.
301
+ #
302
+ # For instance, a time - 24.hours will go subtract exactly 24 hours, while a
303
+ # time - 1.day will subtract 23-25 hours, depending on the day.
304
+ #
305
+ # now - 24.hours # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
306
+ # now - 1.day # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
307
+ #
308
+ # If both the TimeWithZone object and the other value act like Time, a Float
309
+ # will be returned.
310
+ #
311
+ # Time.zone.now - 1.day.ago # => 86399.999967
312
+ #
262
313
  def -(other)
263
- # If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time,
264
- # otherwise move backwards #utc, for accuracy when moving across DST boundaries
265
314
  if other.acts_like?(:time)
266
315
  to_time - other.to_time
267
316
  elsif duration_of_variable_length?(other)
@@ -272,21 +321,84 @@ module ActiveSupport
272
321
  end
273
322
  end
274
323
 
275
- def since(other)
276
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
277
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
278
- if duration_of_variable_length?(other)
279
- method_missing(:since, other)
280
- else
281
- utc.since(other).in_time_zone(time_zone)
282
- end
283
- end
284
- alias_method :in, :since
285
-
324
+ # Subtracts an interval of time from the current object's time and returns
325
+ # the result as a new TimeWithZone object.
326
+ #
327
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
328
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
329
+ # now.ago(1000) # => Mon, 03 Nov 2014 00:09:48 EST -05:00
330
+ #
331
+ # If we're subtracting a Duration of variable length (i.e., years, months,
332
+ # days), move backward from #time, otherwise move backward from #utc, for
333
+ # accuracy when moving across DST boundaries.
334
+ #
335
+ # For instance, <tt>time.ago(24.hours)</tt> will move back exactly 24 hours,
336
+ # while <tt>time.ago(1.day)</tt> will move back 23-25 hours, depending on
337
+ # the day.
338
+ #
339
+ # now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
340
+ # now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
286
341
  def ago(other)
287
342
  since(-other)
288
343
  end
289
344
 
345
+ # Returns a new +ActiveSupport::TimeWithZone+ where one or more of the elements have
346
+ # been changed according to the +options+ parameter. The time options (<tt>:hour</tt>,
347
+ # <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly,
348
+ # so if only the hour is passed, then minute, sec, usec and nsec is set to 0. If the
349
+ # hour and minute is passed, then sec, usec and nsec is set to 0. The +options+
350
+ # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
351
+ # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>,
352
+ # <tt>:nsec</tt>, <tt>:offset</tt>, <tt>:zone</tt>. Pass either <tt>:usec</tt>
353
+ # or <tt>:nsec</tt>, not both. Similarly, pass either <tt>:zone</tt> or
354
+ # <tt>:offset</tt>, not both.
355
+ #
356
+ # t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15 EST -05:00
357
+ # t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15 EST -05:00
358
+ # t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00 EST -05:00
359
+ # t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00 EST -05:00
360
+ # t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
361
+ # t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
362
+ def change(options)
363
+ if options[:zone] && options[:offset]
364
+ raise ArgumentError, "Can't change both :offset and :zone at the same time: #{options.inspect}"
365
+ end
366
+
367
+ new_time = time.change(options)
368
+
369
+ if options[:zone]
370
+ new_zone = ::Time.find_zone(options[:zone])
371
+ elsif options[:offset]
372
+ new_zone = ::Time.find_zone(new_time.utc_offset)
373
+ end
374
+
375
+ new_zone ||= time_zone
376
+ periods = new_zone.periods_for_local(new_time)
377
+
378
+ self.class.new(nil, new_zone, new_time, periods.include?(period) ? period : nil)
379
+ end
380
+
381
+ # Uses Date to provide precise Time calculations for years, months, and days
382
+ # according to the proleptic Gregorian calendar. The result is returned as a
383
+ # new TimeWithZone object.
384
+ #
385
+ # The +options+ parameter takes a hash with any of these keys:
386
+ # <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>,
387
+ # <tt>:hours</tt>, <tt>:minutes</tt>, <tt>:seconds</tt>.
388
+ #
389
+ # If advancing by a value of variable length (i.e., years, weeks, months,
390
+ # days), move forward from #time, otherwise move forward from #utc, for
391
+ # accuracy when moving across DST boundaries.
392
+ #
393
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
394
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
395
+ # now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29 EDT -04:00
396
+ # now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28 EDT -04:00
397
+ # now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28 EST -05:00
398
+ # now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28 EST -05:00
399
+ # now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28 EST -05:00
400
+ # now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28 EST -05:00
401
+ # now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28 EST -05:00
290
402
  def advance(options)
291
403
  # If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
292
404
  # otherwise advance from #utc, for accuracy when moving across DST boundaries
@@ -305,23 +417,44 @@ module ActiveSupport
305
417
  EOV
306
418
  end
307
419
 
420
+ # Returns Array of parts of Time in sequence of
421
+ # [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].
422
+ #
423
+ # now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00
424
+ # now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
308
425
  def to_a
309
426
  [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
310
427
  end
311
428
 
429
+ # Returns the object's date and time as a floating point number of seconds
430
+ # since the Epoch (January 1, 1970 00:00 UTC).
431
+ #
432
+ # Time.zone.now.to_f # => 1417709320.285418
312
433
  def to_f
313
434
  utc.to_f
314
435
  end
315
436
 
437
+ # Returns the object's date and time as an integer number of seconds
438
+ # since the Epoch (January 1, 1970 00:00 UTC).
439
+ #
440
+ # Time.zone.now.to_i # => 1417709320
316
441
  def to_i
317
442
  utc.to_i
318
443
  end
319
444
  alias_method :tv_sec, :to_i
320
445
 
446
+ # Returns the object's date and time as a rational number of seconds
447
+ # since the Epoch (January 1, 1970 00:00 UTC).
448
+ #
449
+ # Time.zone.now.to_r # => (708854548642709/500000)
321
450
  def to_r
322
451
  utc.to_r
323
452
  end
324
453
 
454
+ # Returns an instance of DateTime with the timezone's UTC offset
455
+ #
456
+ # Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
457
+ # Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
325
458
  def to_datetime
326
459
  @to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
327
460
  end
@@ -348,6 +481,11 @@ module ActiveSupport
348
481
  end
349
482
  alias_method :kind_of?, :is_a?
350
483
 
484
+ # An instance of ActiveSupport::TimeWithZone is never blank
485
+ def blank?
486
+ false
487
+ end
488
+
351
489
  def freeze
352
490
  # preload instance variables before freezing
353
491
  period; utc; time; to_datetime; to_time
@@ -382,7 +520,7 @@ module ActiveSupport
382
520
  def method_missing(sym, *args, &block)
383
521
  wrap_with_time_zone time.__send__(sym, *args, &block)
384
522
  rescue NoMethodError => e
385
- raise e, e.message.sub(time.inspect, self.inspect), e.backtrace
523
+ raise e, e.message.sub(time.inspect, inspect), e.backtrace
386
524
  end
387
525
 
388
526
  private
@@ -400,11 +538,13 @@ module ActiveSupport
400
538
  end
401
539
 
402
540
  def transfer_time_values_to_utc_constructor(time)
541
+ # avoid creating another Time object if possible
542
+ return time if time.instance_of?(::Time) && time.utc?
403
543
  ::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + time.subsec)
404
544
  end
405
545
 
406
546
  def duration_of_variable_length?(obj)
407
- ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include?(p[0]) }
547
+ ActiveSupport::Duration === obj && obj.parts.any? { |p| [:years, :months, :weeks, :days].include?(p[0]) }
408
548
  end
409
549
 
410
550
  def wrap_with_time_zone(time)