activesupport 5.0.7.2 → 5.1.7

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +464 -694
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_support.rb +8 -4
  6. data/lib/active_support/all.rb +3 -3
  7. data/lib/active_support/array_inquirer.rb +7 -5
  8. data/lib/active_support/backtrace_cleaner.rb +4 -4
  9. data/lib/active_support/benchmarkable.rb +3 -3
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache.rb +41 -48
  12. data/lib/active_support/cache/file_store.rb +11 -20
  13. data/lib/active_support/cache/mem_cache_store.rb +30 -40
  14. data/lib/active_support/cache/memory_store.rb +13 -13
  15. data/lib/active_support/cache/null_store.rb +4 -4
  16. data/lib/active_support/cache/strategy/local_cache.rb +13 -22
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -5
  18. data/lib/active_support/callbacks.rb +649 -584
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  20. data/lib/active_support/concurrency/share_lock.rb +20 -21
  21. data/lib/active_support/configurable.rb +5 -5
  22. data/lib/active_support/core_ext.rb +1 -2
  23. data/lib/active_support/core_ext/array.rb +7 -7
  24. data/lib/active_support/core_ext/array/access.rb +1 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +15 -15
  26. data/lib/active_support/core_ext/array/grouping.rb +1 -1
  27. data/lib/active_support/core_ext/array/inquiry.rb +1 -1
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +1 -1
  29. data/lib/active_support/core_ext/benchmark.rb +1 -1
  30. data/lib/active_support/core_ext/big_decimal.rb +1 -1
  31. data/lib/active_support/core_ext/big_decimal/conversions.rb +4 -6
  32. data/lib/active_support/core_ext/class.rb +2 -2
  33. data/lib/active_support/core_ext/class/attribute.rb +5 -5
  34. data/lib/active_support/core_ext/class/attribute_accessors.rb +1 -1
  35. data/lib/active_support/core_ext/class/subclasses.rb +18 -4
  36. data/lib/active_support/core_ext/date.rb +5 -5
  37. data/lib/active_support/core_ext/date/acts_like.rb +1 -1
  38. data/lib/active_support/core_ext/date/blank.rb +1 -1
  39. data/lib/active_support/core_ext/date/calculations.rb +8 -8
  40. data/lib/active_support/core_ext/date/conversions.rb +12 -12
  41. data/lib/active_support/core_ext/date/zones.rb +2 -2
  42. data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -22
  43. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  44. data/lib/active_support/core_ext/date_and_time/zones.rb +7 -8
  45. data/lib/active_support/core_ext/date_time.rb +5 -5
  46. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -2
  47. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  48. data/lib/active_support/core_ext/date_time/calculations.rb +20 -10
  49. data/lib/active_support/core_ext/date_time/compatibility.rb +2 -2
  50. data/lib/active_support/core_ext/date_time/conversions.rb +12 -12
  51. data/lib/active_support/core_ext/digest/uuid.rb +4 -4
  52. data/lib/active_support/core_ext/enumerable.rb +23 -12
  53. data/lib/active_support/core_ext/file.rb +1 -1
  54. data/lib/active_support/core_ext/file/atomic.rb +4 -4
  55. data/lib/active_support/core_ext/hash.rb +9 -9
  56. data/lib/active_support/core_ext/hash/compact.rb +12 -9
  57. data/lib/active_support/core_ext/hash/conversions.rb +36 -37
  58. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -2
  59. data/lib/active_support/core_ext/hash/keys.rb +6 -6
  60. data/lib/active_support/core_ext/hash/reverse_merge.rb +1 -1
  61. data/lib/active_support/core_ext/hash/slice.rb +4 -4
  62. data/lib/active_support/core_ext/hash/transform_values.rb +1 -0
  63. data/lib/active_support/core_ext/integer.rb +3 -3
  64. data/lib/active_support/core_ext/integer/inflections.rb +1 -1
  65. data/lib/active_support/core_ext/integer/time.rb +2 -2
  66. data/lib/active_support/core_ext/kernel.rb +4 -4
  67. data/lib/active_support/core_ext/kernel/concern.rb +1 -1
  68. data/lib/active_support/core_ext/kernel/reporting.rb +1 -1
  69. data/lib/active_support/core_ext/load_error.rb +1 -18
  70. data/lib/active_support/core_ext/module.rb +11 -12
  71. data/lib/active_support/core_ext/module/aliasing.rb +3 -48
  72. data/lib/active_support/core_ext/module/attr_internal.rb +4 -4
  73. data/lib/active_support/core_ext/module/attribute_accessors.rb +11 -5
  74. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +20 -13
  75. data/lib/active_support/core_ext/module/concerning.rb +1 -1
  76. data/lib/active_support/core_ext/module/delegation.rb +85 -16
  77. data/lib/active_support/core_ext/module/introspection.rb +3 -11
  78. data/lib/active_support/core_ext/module/reachable.rb +2 -2
  79. data/lib/active_support/core_ext/numeric.rb +4 -4
  80. data/lib/active_support/core_ext/numeric/conversions.rb +3 -9
  81. data/lib/active_support/core_ext/numeric/inquiry.rb +21 -21
  82. data/lib/active_support/core_ext/numeric/time.rb +5 -5
  83. data/lib/active_support/core_ext/object.rb +12 -12
  84. data/lib/active_support/core_ext/object/blank.rb +3 -1
  85. data/lib/active_support/core_ext/object/conversions.rb +4 -4
  86. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  87. data/lib/active_support/core_ext/object/duplicable.rb +34 -4
  88. data/lib/active_support/core_ext/object/inclusion.rb +1 -1
  89. data/lib/active_support/core_ext/object/json.rb +26 -12
  90. data/lib/active_support/core_ext/object/to_param.rb +1 -1
  91. data/lib/active_support/core_ext/object/to_query.rb +8 -5
  92. data/lib/active_support/core_ext/object/try.rb +1 -1
  93. data/lib/active_support/core_ext/object/with_options.rb +12 -1
  94. data/lib/active_support/core_ext/range.rb +4 -4
  95. data/lib/active_support/core_ext/range/conversions.rb +1 -1
  96. data/lib/active_support/core_ext/regexp.rb +4 -0
  97. data/lib/active_support/core_ext/securerandom.rb +3 -3
  98. data/lib/active_support/core_ext/string.rb +13 -13
  99. data/lib/active_support/core_ext/string/access.rb +6 -6
  100. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  101. data/lib/active_support/core_ext/string/filters.rb +3 -3
  102. data/lib/active_support/core_ext/string/indent.rb +4 -4
  103. data/lib/active_support/core_ext/string/inflections.rb +10 -14
  104. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  105. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  106. data/lib/active_support/core_ext/string/output_safety.rb +19 -20
  107. data/lib/active_support/core_ext/string/strip.rb +1 -1
  108. data/lib/active_support/core_ext/string/zones.rb +2 -2
  109. data/lib/active_support/core_ext/time.rb +5 -5
  110. data/lib/active_support/core_ext/time/acts_like.rb +1 -1
  111. data/lib/active_support/core_ext/time/calculations.rb +46 -29
  112. data/lib/active_support/core_ext/time/conversions.rb +15 -12
  113. data/lib/active_support/core_ext/time/zones.rb +3 -3
  114. data/lib/active_support/core_ext/uri.rb +2 -2
  115. data/lib/active_support/dependencies.rb +45 -46
  116. data/lib/active_support/dependencies/interlock.rb +1 -1
  117. data/lib/active_support/deprecation.rb +9 -8
  118. data/lib/active_support/deprecation/behaviors.rb +3 -3
  119. data/lib/active_support/deprecation/constant_accessor.rb +50 -0
  120. data/lib/active_support/deprecation/instance_delegator.rb +2 -2
  121. data/lib/active_support/deprecation/method_wrappers.rb +10 -3
  122. data/lib/active_support/deprecation/proxy_wrappers.rb +6 -4
  123. data/lib/active_support/deprecation/reporting.rb +7 -7
  124. data/lib/active_support/duration.rb +221 -28
  125. data/lib/active_support/duration/iso8601_parser.rb +66 -65
  126. data/lib/active_support/duration/iso8601_serializer.rb +11 -9
  127. data/lib/active_support/evented_file_update_checker.rb +59 -55
  128. data/lib/active_support/execution_wrapper.rb +3 -3
  129. data/lib/active_support/executor.rb +1 -1
  130. data/lib/active_support/file_update_checker.rb +54 -50
  131. data/lib/active_support/gem_version.rb +2 -2
  132. data/lib/active_support/gzip.rb +4 -4
  133. data/lib/active_support/hash_with_indifferent_access.rb +40 -28
  134. data/lib/active_support/i18n.rb +5 -5
  135. data/lib/active_support/i18n_railtie.rb +14 -9
  136. data/lib/active_support/inflections.rb +11 -11
  137. data/lib/active_support/inflector.rb +5 -5
  138. data/lib/active_support/inflector/inflections.rb +11 -9
  139. data/lib/active_support/inflector/methods.rb +52 -51
  140. data/lib/active_support/inflector/transliterate.rb +8 -11
  141. data/lib/active_support/json.rb +2 -2
  142. data/lib/active_support/json/decoding.rb +3 -3
  143. data/lib/active_support/json/encoding.rb +8 -7
  144. data/lib/active_support/key_generator.rb +17 -17
  145. data/lib/active_support/lazy_load_hooks.rb +2 -2
  146. data/lib/active_support/log_subscriber.rb +9 -7
  147. data/lib/active_support/log_subscriber/test_helper.rb +9 -9
  148. data/lib/active_support/logger.rb +3 -3
  149. data/lib/active_support/logger_silence.rb +3 -3
  150. data/lib/active_support/logger_thread_safe_level.rb +1 -1
  151. data/lib/active_support/message_encryptor.rb +77 -35
  152. data/lib/active_support/message_verifier.rb +7 -7
  153. data/lib/active_support/multibyte.rb +2 -2
  154. data/lib/active_support/multibyte/chars.rb +23 -21
  155. data/lib/active_support/multibyte/unicode.rb +68 -89
  156. data/lib/active_support/notifications.rb +7 -5
  157. data/lib/active_support/notifications/fanout.rb +3 -3
  158. data/lib/active_support/notifications/instrumenter.rb +5 -5
  159. data/lib/active_support/number_helper.rb +5 -4
  160. data/lib/active_support/number_helper/number_converter.rb +11 -11
  161. data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -3
  162. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -2
  163. data/lib/active_support/number_helper/number_to_human_converter.rb +8 -10
  164. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -11
  165. data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
  166. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -3
  167. data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -32
  168. data/lib/active_support/number_helper/rounding_helper.rb +64 -0
  169. data/lib/active_support/option_merger.rb +1 -1
  170. data/lib/active_support/ordered_hash.rb +3 -3
  171. data/lib/active_support/ordered_options.rb +6 -4
  172. data/lib/active_support/per_thread_registry.rb +5 -5
  173. data/lib/active_support/rails.rb +12 -6
  174. data/lib/active_support/railtie.rb +3 -3
  175. data/lib/active_support/reloader.rb +1 -1
  176. data/lib/active_support/rescuable.rb +6 -6
  177. data/lib/active_support/security_utils.rb +1 -1
  178. data/lib/active_support/string_inquirer.rb +8 -2
  179. data/lib/active_support/subscriber.rb +9 -5
  180. data/lib/active_support/tagged_logging.rb +4 -4
  181. data/lib/active_support/test_case.rb +12 -29
  182. data/lib/active_support/testing/assertions.rb +100 -2
  183. data/lib/active_support/testing/autorun.rb +2 -2
  184. data/lib/active_support/testing/constant_lookup.rb +0 -1
  185. data/lib/active_support/testing/declarative.rb +1 -1
  186. data/lib/active_support/testing/deprecation.rb +3 -2
  187. data/lib/active_support/testing/isolation.rb +15 -22
  188. data/lib/active_support/testing/method_call_assertions.rb +1 -1
  189. data/lib/active_support/testing/setup_and_teardown.rb +2 -2
  190. data/lib/active_support/testing/stream.rb +28 -28
  191. data/lib/active_support/testing/tagged_logging.rb +1 -1
  192. data/lib/active_support/testing/time_helpers.rb +45 -11
  193. data/lib/active_support/time.rb +12 -12
  194. data/lib/active_support/time_with_zone.rb +16 -14
  195. data/lib/active_support/values/time_zone.rb +100 -31
  196. data/lib/active_support/values/unicode_tables.dat +0 -0
  197. data/lib/active_support/version.rb +1 -1
  198. data/lib/active_support/xml_mini.rb +34 -36
  199. data/lib/active_support/xml_mini/jdom.rb +112 -112
  200. data/lib/active_support/xml_mini/libxml.rb +12 -11
  201. data/lib/active_support/xml_mini/libxmlsax.rb +13 -14
  202. data/lib/active_support/xml_mini/nokogiri.rb +10 -10
  203. data/lib/active_support/xml_mini/nokogirisax.rb +12 -13
  204. data/lib/active_support/xml_mini/rexml.rb +9 -9
  205. metadata +8 -9
  206. data/lib/active_support/concurrency/latch.rb +0 -26
  207. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  208. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  209. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  210. data/lib/active_support/core_ext/struct.rb +0 -3
  211. data/lib/active_support/core_ext/time/marshal.rb +0 -3
@@ -1,5 +1,5 @@
1
- gem 'minitest'
1
+ gem "minitest"
2
2
 
3
- require 'minitest'
3
+ require "minitest"
4
4
 
5
5
  Minitest.autorun
@@ -44,7 +44,6 @@ module ActiveSupport
44
44
  end
45
45
  end
46
46
  end
47
-
48
47
  end
49
48
  end
50
49
  end
@@ -9,7 +9,7 @@ module ActiveSupport
9
9
  # ...
10
10
  # end
11
11
  def test(name, &block)
12
- test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
12
+ test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
13
13
  defined = method_defined? test_name
14
14
  raise "#{test_name} is already defined in #{self}" if defined
15
15
  if block_given?
@@ -1,4 +1,5 @@
1
- require 'active_support/deprecation'
1
+ require "active_support/deprecation"
2
+ require "active_support/core_ext/regexp"
2
3
 
3
4
  module ActiveSupport
4
5
  module Testing
@@ -8,7 +9,7 @@ module ActiveSupport
8
9
  assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
9
10
  if match
10
11
  match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
11
- assert warnings.any? { |w| w =~ match }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
12
+ assert warnings.any? { |w| match.match?(w) }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
12
13
  end
13
14
  result
14
15
  end
@@ -1,7 +1,7 @@
1
1
  module ActiveSupport
2
2
  module Testing
3
3
  module Isolation
4
- require 'thread'
4
+ require "thread"
5
5
 
6
6
  def self.included(klass) #:nodoc:
7
7
  klass.class_eval do
@@ -13,17 +13,6 @@ module ActiveSupport
13
13
  !ENV["NO_FORK"] && Process.respond_to?(:fork)
14
14
  end
15
15
 
16
- @@class_setup_mutex = Mutex.new
17
-
18
- def _run_class_setup # class setup method should only happen in parent
19
- @@class_setup_mutex.synchronize do
20
- unless defined?(@@ran_class_setup) || ENV['ISOLATION_TEST']
21
- self.class.setup if self.class.respond_to?(:setup)
22
- @@ran_class_setup = true
23
- end
24
- end
25
- end
26
-
27
16
  def run
28
17
  serialized = run_in_isolation do
29
18
  super
@@ -54,7 +43,8 @@ module ActiveSupport
54
43
  end
55
44
  }
56
45
  end
57
- result = Marshal.dump(self.dup)
46
+ test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
47
+ result = Marshal.dump(test_result)
58
48
  end
59
49
 
60
50
  write.puts [result].pack("m")
@@ -78,24 +68,27 @@ module ActiveSupport
78
68
 
79
69
  if ENV["ISOLATION_TEST"]
80
70
  yield
71
+ test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
81
72
  File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
82
- file.puts [Marshal.dump(self.dup)].pack("m")
73
+ file.puts [Marshal.dump(test_result)].pack("m")
83
74
  end
84
75
  exit!
85
76
  else
86
77
  Tempfile.open("isolation") do |tmpfile|
87
78
  env = {
88
- 'ISOLATION_TEST' => self.class.name,
89
- 'ISOLATION_OUTPUT' => tmpfile.path
79
+ "ISOLATION_TEST" => self.class.name,
80
+ "ISOLATION_OUTPUT" => tmpfile.path
90
81
  }
91
82
 
92
- load_paths = $-I.map {|p| "-I\"#{File.expand_path(p)}\"" }.join(" ")
93
- orig_args = ORIG_ARGV.join(" ")
94
- test_opts = "-n#{self.class.name}##{self.name}"
95
- command = "#{Gem.ruby} #{load_paths} #{$0} '#{orig_args}' #{test_opts}"
83
+ test_opts = "-n#{self.class.name}##{name}"
84
+
85
+ load_path_args = []
86
+ $-I.each do |p|
87
+ load_path_args << "-I"
88
+ load_path_args << File.expand_path(p)
89
+ end
96
90
 
97
- # IO.popen lets us pass env in a cross-platform way
98
- child = IO.popen(env, command)
91
+ child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
99
92
 
100
93
  begin
101
94
  Process.wait(child.pid)
@@ -1,4 +1,4 @@
1
- require 'minitest/mock'
1
+ require "minitest/mock"
2
2
 
3
3
  module ActiveSupport
4
4
  module Testing
@@ -1,5 +1,5 @@
1
- require 'active_support/concern'
2
- require 'active_support/callbacks'
1
+ require "active_support/concern"
2
+ require "active_support/callbacks"
3
3
 
4
4
  module ActiveSupport
5
5
  module Testing
@@ -3,40 +3,40 @@ module ActiveSupport
3
3
  module Stream #:nodoc:
4
4
  private
5
5
 
6
- def silence_stream(stream)
7
- old_stream = stream.dup
8
- stream.reopen(IO::NULL)
9
- stream.sync = true
10
- yield
11
- ensure
12
- stream.reopen(old_stream)
13
- old_stream.close
14
- end
6
+ def silence_stream(stream)
7
+ old_stream = stream.dup
8
+ stream.reopen(IO::NULL)
9
+ stream.sync = true
10
+ yield
11
+ ensure
12
+ stream.reopen(old_stream)
13
+ old_stream.close
14
+ end
15
15
 
16
- def quietly
17
- silence_stream(STDOUT) do
18
- silence_stream(STDERR) do
19
- yield
16
+ def quietly
17
+ silence_stream(STDOUT) do
18
+ silence_stream(STDERR) do
19
+ yield
20
+ end
20
21
  end
21
22
  end
22
- end
23
23
 
24
- def capture(stream)
25
- stream = stream.to_s
26
- captured_stream = Tempfile.new(stream)
27
- stream_io = eval("$#{stream}")
28
- origin_stream = stream_io.dup
29
- stream_io.reopen(captured_stream)
24
+ def capture(stream)
25
+ stream = stream.to_s
26
+ captured_stream = Tempfile.new(stream)
27
+ stream_io = eval("$#{stream}")
28
+ origin_stream = stream_io.dup
29
+ stream_io.reopen(captured_stream)
30
30
 
31
- yield
31
+ yield
32
32
 
33
- stream_io.rewind
34
- return captured_stream.read
35
- ensure
36
- captured_stream.close
37
- captured_stream.unlink
38
- stream_io.reopen(origin_stream)
39
- end
33
+ stream_io.rewind
34
+ return captured_stream.read
35
+ ensure
36
+ captured_stream.close
37
+ captured_stream.unlink
38
+ stream_io.reopen(origin_stream)
39
+ end
40
40
  end
41
41
  end
42
42
  end
@@ -8,7 +8,7 @@ module ActiveSupport
8
8
  def before_setup
9
9
  if tagged_logger && tagged_logger.info?
10
10
  heading = "#{self.class}: #{name}"
11
- divider = '-' * heading.size
11
+ divider = "-" * heading.size
12
12
  tagged_logger.info divider
13
13
  tagged_logger.info heading
14
14
  tagged_logger.info divider
@@ -1,4 +1,6 @@
1
+ require "active_support/core_ext/string/strip" # for strip_heredoc
1
2
  require "active_support/core_ext/time/calculations"
3
+ require "concurrent/map"
2
4
 
3
5
  module ActiveSupport
4
6
  module Testing
@@ -6,29 +8,33 @@ module ActiveSupport
6
8
  Stub = Struct.new(:object, :method_name, :original_method)
7
9
 
8
10
  def initialize
9
- @stubs = {}
11
+ @stubs = Concurrent::Map.new { |h, k| h[k] = {} }
10
12
  end
11
13
 
12
14
  def stub_object(object, method_name, &block)
13
- key = [object.object_id, method_name]
14
-
15
- if stub = @stubs[key]
15
+ if stub = stubbing(object, method_name)
16
16
  unstub_object(stub)
17
17
  end
18
18
 
19
19
  new_name = "__simple_stub__#{method_name}"
20
20
 
21
- @stubs[key] = Stub.new(object, method_name, new_name)
21
+ @stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
22
22
 
23
23
  object.singleton_class.send :alias_method, new_name, method_name
24
24
  object.define_singleton_method(method_name, &block)
25
25
  end
26
26
 
27
27
  def unstub_all!
28
- @stubs.each_value do |stub|
29
- unstub_object(stub)
28
+ @stubs.each_value do |object_stubs|
29
+ object_stubs.each_value do |stub|
30
+ unstub_object(stub)
31
+ end
30
32
  end
31
- @stubs = {}
33
+ @stubs.clear
34
+ end
35
+
36
+ def stubbing(object, method_name)
37
+ @stubs[object.object_id][method_name]
32
38
  end
33
39
 
34
40
  private
@@ -68,7 +74,7 @@ module ActiveSupport
68
74
  # +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
69
75
  #
70
76
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
71
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
77
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
72
78
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
73
79
  # Date.current # => Wed, 24 Nov 2004
74
80
  # DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
@@ -90,11 +96,39 @@ module ActiveSupport
90
96
  # state at the end of the block:
91
97
  #
92
98
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
93
- # travel_to Time.new(2004, 11, 24, 01, 04, 44) do
99
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44) do
94
100
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
95
101
  # end
96
102
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
97
103
  def travel_to(date_or_time)
104
+ if block_given? && simple_stubs.stubbing(Time, :now)
105
+ travel_to_nested_block_call = <<-MSG.strip_heredoc
106
+
107
+ Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
108
+
109
+ Instead of:
110
+
111
+ travel_to 2.days.from_now do
112
+ # 2 days from today
113
+ travel_to 3.days.from_now do
114
+ # 5 days from today
115
+ end
116
+ end
117
+
118
+ preferred way to achieve above is:
119
+
120
+ travel 2.days do
121
+ # 2 days from today
122
+ end
123
+
124
+ travel 5.days do
125
+ # 5 days from today
126
+ end
127
+
128
+ MSG
129
+ raise travel_to_nested_block_call
130
+ end
131
+
98
132
  if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
99
133
  now = date_or_time.midnight.to_time
100
134
  else
@@ -118,7 +152,7 @@ module ActiveSupport
118
152
  # `travel` and `travel_to`.
119
153
  #
120
154
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
121
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
155
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
122
156
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
123
157
  # travel_back
124
158
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
@@ -1,18 +1,18 @@
1
1
  module ActiveSupport
2
- autoload :Duration, 'active_support/duration'
3
- autoload :TimeWithZone, 'active_support/time_with_zone'
4
- autoload :TimeZone, 'active_support/values/time_zone'
2
+ autoload :Duration, "active_support/duration"
3
+ autoload :TimeWithZone, "active_support/time_with_zone"
4
+ autoload :TimeZone, "active_support/values/time_zone"
5
5
  end
6
6
 
7
- require 'date'
8
- require 'time'
7
+ require "date"
8
+ require "time"
9
9
 
10
- require 'active_support/core_ext/time'
11
- require 'active_support/core_ext/date'
12
- require 'active_support/core_ext/date_time'
10
+ require "active_support/core_ext/time"
11
+ require "active_support/core_ext/date"
12
+ require "active_support/core_ext/date_time"
13
13
 
14
- require 'active_support/core_ext/integer/time'
15
- require 'active_support/core_ext/numeric/time'
14
+ require "active_support/core_ext/integer/time"
15
+ require "active_support/core_ext/numeric/time"
16
16
 
17
- require 'active_support/core_ext/string/conversions'
18
- require 'active_support/core_ext/string/zones'
17
+ require "active_support/core_ext/string/conversions"
18
+ require "active_support/core_ext/string/zones"
@@ -1,7 +1,7 @@
1
- require 'active_support/duration'
2
- require 'active_support/values/time_zone'
3
- require 'active_support/core_ext/object/acts_like'
4
- require 'active_support/core_ext/date_and_time/compatibility'
1
+ require "active_support/duration"
2
+ require "active_support/values/time_zone"
3
+ require "active_support/core_ext/object/acts_like"
4
+ require "active_support/core_ext/date_and_time/compatibility"
5
5
 
6
6
  module ActiveSupport
7
7
  # A Time-like class that can represent a time in any time zone. Necessary
@@ -36,14 +36,13 @@ module ActiveSupport
36
36
  # t.is_a?(Time) # => true
37
37
  # t.is_a?(ActiveSupport::TimeWithZone) # => true
38
38
  class TimeWithZone
39
-
40
39
  # Report class name as 'Time' to thwart type checking.
41
40
  def self.name
42
- 'Time'
41
+ "Time"
43
42
  end
44
43
 
45
44
  PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N".freeze }
46
- PRECISIONS[0] = '%FT%T'.freeze
45
+ PRECISIONS[0] = "%FT%T".freeze
47
46
 
48
47
  include Comparable, DateAndTime::Compatibility
49
48
  attr_reader :time_zone
@@ -134,7 +133,7 @@ module ActiveSupport
134
133
  period.zone_identifier.to_s
135
134
  end
136
135
 
137
- # Returns a string of the object's date, time, zone and offset from UTC.
136
+ # Returns a string of the object's date, time, zone, and offset from UTC.
138
137
  #
139
138
  # Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
140
139
  def inspect
@@ -149,6 +148,7 @@ module ActiveSupport
149
148
  "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'.freeze)}"
150
149
  end
151
150
  alias_method :iso8601, :xmlschema
151
+ alias_method :rfc3339, :xmlschema
152
152
 
153
153
  # Coerces time to a string for JSON encoding. The default format is ISO 8601.
154
154
  # You can get %Y/%m/%d %H:%M:%S +offset style by setting
@@ -171,12 +171,12 @@ module ActiveSupport
171
171
  end
172
172
 
173
173
  def init_with(coder) #:nodoc:
174
- initialize(coder['utc'], coder['zone'], coder['time'])
174
+ initialize(coder["utc"], coder["zone"], coder["time"])
175
175
  end
176
176
 
177
177
  def encode_with(coder) #:nodoc:
178
- coder.tag = '!ruby/object:ActiveSupport::TimeWithZone'
179
- coder.map = { 'utc' => utc, 'zone' => time_zone, 'time' => time }
178
+ coder.tag = "!ruby/object:ActiveSupport::TimeWithZone"
179
+ coder.map = { "utc" => utc, "zone" => time_zone, "time" => time }
180
180
  end
181
181
 
182
182
  # Returns a string of the object's date and time in the format used by
@@ -408,7 +408,7 @@ module ActiveSupport
408
408
  # Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
409
409
  # Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
410
410
  def to_datetime
411
- utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
411
+ @to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
412
412
  end
413
413
 
414
414
  # Returns an instance of +Time+, either with the same UTC offset
@@ -472,7 +472,7 @@ module ActiveSupport
472
472
  def method_missing(sym, *args, &block)
473
473
  wrap_with_time_zone time.__send__(sym, *args, &block)
474
474
  rescue NoMethodError => e
475
- raise e, e.message.sub(time.inspect, self.inspect), e.backtrace
475
+ raise e, e.message.sub(time.inspect, inspect), e.backtrace
476
476
  end
477
477
 
478
478
  private
@@ -490,11 +490,13 @@ module ActiveSupport
490
490
  end
491
491
 
492
492
  def transfer_time_values_to_utc_constructor(time)
493
+ # avoid creating another Time object if possible
494
+ return time if time.instance_of?(::Time) && time.utc?
493
495
  ::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + time.subsec)
494
496
  end
495
497
 
496
498
  def duration_of_variable_length?(obj)
497
- ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :weeks, :days].include?(p[0]) }
499
+ ActiveSupport::Duration === obj && obj.parts.any? { |p| [:years, :months, :weeks, :days].include?(p[0]) }
498
500
  end
499
501
 
500
502
  def wrap_with_time_zone(time)
@@ -1,6 +1,6 @@
1
- require 'tzinfo'
2
- require 'concurrent/map'
3
- require 'active_support/core_ext/object/blank'
1
+ require "tzinfo"
2
+ require "concurrent/map"
3
+ require "active_support/core_ext/object/blank"
4
4
 
5
5
  module ActiveSupport
6
6
  # The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
@@ -180,8 +180,8 @@ module ActiveSupport
180
180
  "Samoa" => "Pacific/Apia"
181
181
  }
182
182
 
183
- UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
184
- UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(':', '')
183
+ UTC_OFFSET_WITH_COLON = "%s%02d:%02d"
184
+ UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(":", "")
185
185
 
186
186
  @lazy_zones_map = Concurrent::Map.new
187
187
  @country_zones = Concurrent::Map.new
@@ -193,7 +193,7 @@ module ActiveSupport
193
193
  # ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
194
194
  def seconds_to_utc_offset(seconds, colon = true)
195
195
  format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
196
- sign = (seconds < 0 ? '-' : '+')
196
+ sign = (seconds < 0 ? "-" : "+")
197
197
  hours = seconds.abs / 3600
198
198
  minutes = (seconds.abs % 3600) / 60
199
199
  format % [sign, hours, minutes]
@@ -226,17 +226,17 @@ module ActiveSupport
226
226
  # Returns +nil+ if no such time zone is known to the system.
227
227
  def [](arg)
228
228
  case arg
229
- when String
229
+ when String
230
230
  begin
231
231
  @lazy_zones_map[arg] ||= create(arg)
232
232
  rescue TZInfo::InvalidTimezoneIdentifier
233
233
  nil
234
234
  end
235
- when Numeric, ActiveSupport::Duration
236
- arg *= 3600 if arg.abs <= 13
237
- all.find { |z| z.utc_offset == arg.to_i }
235
+ when Numeric, ActiveSupport::Duration
236
+ arg *= 3600 if arg.abs <= 13
237
+ all.find { |z| z.utc_offset == arg.to_i }
238
238
  else
239
- raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
239
+ raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
240
240
  end
241
241
  end
242
242
 
@@ -270,7 +270,7 @@ module ActiveSupport
270
270
 
271
271
  def zones_map
272
272
  @zones_map ||= begin
273
- MAPPING.each_key {|place| self[place]} # load all the zones
273
+ MAPPING.each_key { |place| self[place] } # load all the zones
274
274
  @lazy_zones_map
275
275
  end
276
276
  end
@@ -305,7 +305,7 @@ module ActiveSupport
305
305
  # zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
306
306
  # zone.formatted_offset # => "-06:00"
307
307
  # zone.formatted_offset(false) # => "-0600"
308
- def formatted_offset(colon=true, alternate_utc_string = nil)
308
+ def formatted_offset(colon = true, alternate_utc_string = nil)
309
309
  utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
310
310
  end
311
311
 
@@ -349,6 +349,41 @@ module ActiveSupport
349
349
  Time.at(secs).utc.in_time_zone(self)
350
350
  end
351
351
 
352
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
353
+ # of +self+ from an ISO 8601 string.
354
+ #
355
+ # Time.zone = 'Hawaii' # => "Hawaii"
356
+ # Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
357
+ #
358
+ # If the time components are missing then they will be set to zero.
359
+ #
360
+ # Time.zone = 'Hawaii' # => "Hawaii"
361
+ # Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
362
+ #
363
+ # If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
364
+ # which returns +nil+ when given an invalid date string.
365
+ def iso8601(str)
366
+ parts = Date._iso8601(str)
367
+
368
+ raise ArgumentError, "invalid date" if parts.empty?
369
+
370
+ time = Time.new(
371
+ parts.fetch(:year),
372
+ parts.fetch(:mon),
373
+ parts.fetch(:mday),
374
+ parts.fetch(:hour, 0),
375
+ parts.fetch(:min, 0),
376
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
377
+ parts.fetch(:offset, 0)
378
+ )
379
+
380
+ if parts[:offset]
381
+ TimeWithZone.new(time.utc, self)
382
+ else
383
+ TimeWithZone.new(nil, self, time)
384
+ end
385
+ end
386
+
352
387
  # Method for creating new ActiveSupport::TimeWithZone instance in time zone
353
388
  # of +self+ from parsed string.
354
389
  #
@@ -365,10 +400,40 @@ module ActiveSupport
365
400
  # components are supplied, then the day of the month defaults to 1:
366
401
  #
367
402
  # Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
368
- def parse(str, now=now())
403
+ def parse(str, now = now())
369
404
  parts_to_time(Date._parse(str, false), now)
370
405
  end
371
406
 
407
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
408
+ # of +self+ from an RFC 3339 string.
409
+ #
410
+ # Time.zone = 'Hawaii' # => "Hawaii"
411
+ # Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
412
+ #
413
+ # If the time or zone components are missing then an +ArgumentError+ will
414
+ # be raised. This is much stricter than either +parse+ or +iso8601+ which
415
+ # allow for missing components.
416
+ #
417
+ # Time.zone = 'Hawaii' # => "Hawaii"
418
+ # Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
419
+ def rfc3339(str)
420
+ parts = Date._rfc3339(str)
421
+
422
+ raise ArgumentError, "invalid date" if parts.empty?
423
+
424
+ time = Time.new(
425
+ parts.fetch(:year),
426
+ parts.fetch(:mon),
427
+ parts.fetch(:mday),
428
+ parts.fetch(:hour),
429
+ parts.fetch(:min),
430
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
431
+ parts.fetch(:offset)
432
+ )
433
+
434
+ TimeWithZone.new(time.utc, self)
435
+ end
436
+
372
437
  # Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
373
438
  #
374
439
  # Assumes that +str+ is a time in the time zone +self+,
@@ -389,7 +454,7 @@ module ActiveSupport
389
454
  # components are supplied, then the day of the month defaults to 1:
390
455
  #
391
456
  # Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
392
- def strptime(str, format, now=now())
457
+ def strptime(str, format, now = now())
393
458
  parts_to_time(DateTime._strptime(str, format), now)
394
459
  end
395
460
 
@@ -426,7 +491,7 @@ module ActiveSupport
426
491
 
427
492
  # Adjust the given time to the simultaneous time in UTC. Returns a
428
493
  # Time.utc() instance.
429
- def local_to_utc(time, dst=true)
494
+ def local_to_utc(time, dst = true)
430
495
  tzinfo.local_to_utc(time, dst)
431
496
  end
432
497
 
@@ -438,7 +503,7 @@ module ActiveSupport
438
503
 
439
504
  # Available so that TimeZone instances respond like TZInfo::Timezone
440
505
  # instances.
441
- def period_for_local(time, dst=true)
506
+ def period_for_local(time, dst = true)
442
507
  tzinfo.period_for_local(time, dst)
443
508
  end
444
509
 
@@ -447,12 +512,12 @@ module ActiveSupport
447
512
  end
448
513
 
449
514
  def init_with(coder) #:nodoc:
450
- initialize(coder['name'])
515
+ initialize(coder["name"])
451
516
  end
452
517
 
453
518
  def encode_with(coder) #:nodoc:
454
- coder.tag ="!ruby/object:#{self.class}"
455
- coder.map = { 'name' => tzinfo.name }
519
+ coder.tag = "!ruby/object:#{self.class}"
520
+ coder.map = { "name" => tzinfo.name }
456
521
  end
457
522
 
458
523
  private
@@ -460,17 +525,21 @@ module ActiveSupport
460
525
  raise ArgumentError, "invalid date" if parts.nil?
461
526
  return if parts.empty?
462
527
 
463
- time = Time.new(
464
- parts.fetch(:year, now.year),
465
- parts.fetch(:mon, now.month),
466
- parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
467
- parts.fetch(:hour, 0),
468
- parts.fetch(:min, 0),
469
- parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
470
- parts.fetch(:offset, 0)
471
- )
472
-
473
- if parts[:offset]
528
+ if parts[:seconds]
529
+ time = Time.at(parts[:seconds])
530
+ else
531
+ time = Time.new(
532
+ parts.fetch(:year, now.year),
533
+ parts.fetch(:mon, now.month),
534
+ parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
535
+ parts.fetch(:hour, 0),
536
+ parts.fetch(:min, 0),
537
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
538
+ parts.fetch(:offset, 0)
539
+ )
540
+ end
541
+
542
+ if parts[:offset] || parts[:seconds]
474
543
  TimeWithZone.new(time.utc, self)
475
544
  else
476
545
  TimeWithZone.new(nil, self, time)