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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +464 -694
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_support.rb +8 -4
- data/lib/active_support/all.rb +3 -3
- data/lib/active_support/array_inquirer.rb +7 -5
- data/lib/active_support/backtrace_cleaner.rb +4 -4
- data/lib/active_support/benchmarkable.rb +3 -3
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache.rb +41 -48
- data/lib/active_support/cache/file_store.rb +11 -20
- data/lib/active_support/cache/mem_cache_store.rb +30 -40
- data/lib/active_support/cache/memory_store.rb +13 -13
- data/lib/active_support/cache/null_store.rb +4 -4
- data/lib/active_support/cache/strategy/local_cache.rb +13 -22
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -5
- data/lib/active_support/callbacks.rb +649 -584
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
- data/lib/active_support/concurrency/share_lock.rb +20 -21
- data/lib/active_support/configurable.rb +5 -5
- data/lib/active_support/core_ext.rb +1 -2
- data/lib/active_support/core_ext/array.rb +7 -7
- data/lib/active_support/core_ext/array/access.rb +1 -1
- data/lib/active_support/core_ext/array/conversions.rb +15 -15
- data/lib/active_support/core_ext/array/grouping.rb +1 -1
- data/lib/active_support/core_ext/array/inquiry.rb +1 -1
- data/lib/active_support/core_ext/array/prepend_and_append.rb +1 -1
- data/lib/active_support/core_ext/benchmark.rb +1 -1
- data/lib/active_support/core_ext/big_decimal.rb +1 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +4 -6
- data/lib/active_support/core_ext/class.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +5 -5
- data/lib/active_support/core_ext/class/attribute_accessors.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -4
- data/lib/active_support/core_ext/date.rb +5 -5
- data/lib/active_support/core_ext/date/acts_like.rb +1 -1
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +8 -8
- data/lib/active_support/core_ext/date/conversions.rb +12 -12
- data/lib/active_support/core_ext/date/zones.rb +2 -2
- data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -22
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +7 -8
- data/lib/active_support/core_ext/date_time.rb +5 -5
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -2
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +20 -10
- data/lib/active_support/core_ext/date_time/compatibility.rb +2 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +12 -12
- data/lib/active_support/core_ext/digest/uuid.rb +4 -4
- data/lib/active_support/core_ext/enumerable.rb +23 -12
- data/lib/active_support/core_ext/file.rb +1 -1
- data/lib/active_support/core_ext/file/atomic.rb +4 -4
- data/lib/active_support/core_ext/hash.rb +9 -9
- data/lib/active_support/core_ext/hash/compact.rb +12 -9
- data/lib/active_support/core_ext/hash/conversions.rb +36 -37
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -2
- data/lib/active_support/core_ext/hash/keys.rb +6 -6
- data/lib/active_support/core_ext/hash/reverse_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/slice.rb +4 -4
- data/lib/active_support/core_ext/hash/transform_values.rb +1 -0
- data/lib/active_support/core_ext/integer.rb +3 -3
- data/lib/active_support/core_ext/integer/inflections.rb +1 -1
- data/lib/active_support/core_ext/integer/time.rb +2 -2
- data/lib/active_support/core_ext/kernel.rb +4 -4
- data/lib/active_support/core_ext/kernel/concern.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +1 -1
- data/lib/active_support/core_ext/load_error.rb +1 -18
- data/lib/active_support/core_ext/module.rb +11 -12
- data/lib/active_support/core_ext/module/aliasing.rb +3 -48
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -4
- data/lib/active_support/core_ext/module/attribute_accessors.rb +11 -5
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +20 -13
- data/lib/active_support/core_ext/module/concerning.rb +1 -1
- data/lib/active_support/core_ext/module/delegation.rb +85 -16
- data/lib/active_support/core_ext/module/introspection.rb +3 -11
- data/lib/active_support/core_ext/module/reachable.rb +2 -2
- data/lib/active_support/core_ext/numeric.rb +4 -4
- data/lib/active_support/core_ext/numeric/conversions.rb +3 -9
- data/lib/active_support/core_ext/numeric/inquiry.rb +21 -21
- data/lib/active_support/core_ext/numeric/time.rb +5 -5
- data/lib/active_support/core_ext/object.rb +12 -12
- data/lib/active_support/core_ext/object/blank.rb +3 -1
- data/lib/active_support/core_ext/object/conversions.rb +4 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +34 -4
- data/lib/active_support/core_ext/object/inclusion.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +26 -12
- data/lib/active_support/core_ext/object/to_param.rb +1 -1
- data/lib/active_support/core_ext/object/to_query.rb +8 -5
- data/lib/active_support/core_ext/object/try.rb +1 -1
- data/lib/active_support/core_ext/object/with_options.rb +12 -1
- data/lib/active_support/core_ext/range.rb +4 -4
- data/lib/active_support/core_ext/range/conversions.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +4 -0
- data/lib/active_support/core_ext/securerandom.rb +3 -3
- data/lib/active_support/core_ext/string.rb +13 -13
- data/lib/active_support/core_ext/string/access.rb +6 -6
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/indent.rb +4 -4
- data/lib/active_support/core_ext/string/inflections.rb +10 -14
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +19 -20
- data/lib/active_support/core_ext/string/strip.rb +1 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -2
- data/lib/active_support/core_ext/time.rb +5 -5
- data/lib/active_support/core_ext/time/acts_like.rb +1 -1
- data/lib/active_support/core_ext/time/calculations.rb +46 -29
- data/lib/active_support/core_ext/time/conversions.rb +15 -12
- data/lib/active_support/core_ext/time/zones.rb +3 -3
- data/lib/active_support/core_ext/uri.rb +2 -2
- data/lib/active_support/dependencies.rb +45 -46
- data/lib/active_support/dependencies/interlock.rb +1 -1
- data/lib/active_support/deprecation.rb +9 -8
- data/lib/active_support/deprecation/behaviors.rb +3 -3
- data/lib/active_support/deprecation/constant_accessor.rb +50 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -2
- data/lib/active_support/deprecation/method_wrappers.rb +10 -3
- data/lib/active_support/deprecation/proxy_wrappers.rb +6 -4
- data/lib/active_support/deprecation/reporting.rb +7 -7
- data/lib/active_support/duration.rb +221 -28
- data/lib/active_support/duration/iso8601_parser.rb +66 -65
- data/lib/active_support/duration/iso8601_serializer.rb +11 -9
- data/lib/active_support/evented_file_update_checker.rb +59 -55
- data/lib/active_support/execution_wrapper.rb +3 -3
- data/lib/active_support/executor.rb +1 -1
- data/lib/active_support/file_update_checker.rb +54 -50
- data/lib/active_support/gem_version.rb +2 -2
- data/lib/active_support/gzip.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +40 -28
- data/lib/active_support/i18n.rb +5 -5
- data/lib/active_support/i18n_railtie.rb +14 -9
- data/lib/active_support/inflections.rb +11 -11
- data/lib/active_support/inflector.rb +5 -5
- data/lib/active_support/inflector/inflections.rb +11 -9
- data/lib/active_support/inflector/methods.rb +52 -51
- data/lib/active_support/inflector/transliterate.rb +8 -11
- data/lib/active_support/json.rb +2 -2
- data/lib/active_support/json/decoding.rb +3 -3
- data/lib/active_support/json/encoding.rb +8 -7
- data/lib/active_support/key_generator.rb +17 -17
- data/lib/active_support/lazy_load_hooks.rb +2 -2
- data/lib/active_support/log_subscriber.rb +9 -7
- data/lib/active_support/log_subscriber/test_helper.rb +9 -9
- data/lib/active_support/logger.rb +3 -3
- data/lib/active_support/logger_silence.rb +3 -3
- data/lib/active_support/logger_thread_safe_level.rb +1 -1
- data/lib/active_support/message_encryptor.rb +77 -35
- data/lib/active_support/message_verifier.rb +7 -7
- data/lib/active_support/multibyte.rb +2 -2
- data/lib/active_support/multibyte/chars.rb +23 -21
- data/lib/active_support/multibyte/unicode.rb +68 -89
- data/lib/active_support/notifications.rb +7 -5
- data/lib/active_support/notifications/fanout.rb +3 -3
- data/lib/active_support/notifications/instrumenter.rb +5 -5
- data/lib/active_support/number_helper.rb +5 -4
- data/lib/active_support/number_helper/number_converter.rb +11 -11
- data/lib/active_support/number_helper/number_to_currency_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +8 -10
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -11
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -3
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -32
- data/lib/active_support/number_helper/rounding_helper.rb +64 -0
- data/lib/active_support/option_merger.rb +1 -1
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +6 -4
- data/lib/active_support/per_thread_registry.rb +5 -5
- data/lib/active_support/rails.rb +12 -6
- data/lib/active_support/railtie.rb +3 -3
- data/lib/active_support/reloader.rb +1 -1
- data/lib/active_support/rescuable.rb +6 -6
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/string_inquirer.rb +8 -2
- data/lib/active_support/subscriber.rb +9 -5
- data/lib/active_support/tagged_logging.rb +4 -4
- data/lib/active_support/test_case.rb +12 -29
- data/lib/active_support/testing/assertions.rb +100 -2
- data/lib/active_support/testing/autorun.rb +2 -2
- data/lib/active_support/testing/constant_lookup.rb +0 -1
- data/lib/active_support/testing/declarative.rb +1 -1
- data/lib/active_support/testing/deprecation.rb +3 -2
- data/lib/active_support/testing/isolation.rb +15 -22
- data/lib/active_support/testing/method_call_assertions.rb +1 -1
- data/lib/active_support/testing/setup_and_teardown.rb +2 -2
- data/lib/active_support/testing/stream.rb +28 -28
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +45 -11
- data/lib/active_support/time.rb +12 -12
- data/lib/active_support/time_with_zone.rb +16 -14
- data/lib/active_support/values/time_zone.rb +100 -31
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini.rb +34 -36
- data/lib/active_support/xml_mini/jdom.rb +112 -112
- data/lib/active_support/xml_mini/libxml.rb +12 -11
- data/lib/active_support/xml_mini/libxmlsax.rb +13 -14
- data/lib/active_support/xml_mini/nokogiri.rb +10 -10
- data/lib/active_support/xml_mini/nokogirisax.rb +12 -13
- data/lib/active_support/xml_mini/rexml.rb +9 -9
- metadata +8 -9
- data/lib/active_support/concurrency/latch.rb +0 -26
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
- data/lib/active_support/core_ext/struct.rb +0 -3
- data/lib/active_support/core_ext/time/marshal.rb +0 -3
@@ -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
|
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
|
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
|
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
|
-
|
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(
|
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
|
-
|
89
|
-
|
79
|
+
"ISOLATION_TEST" => self.class.name,
|
80
|
+
"ISOLATION_OUTPUT" => tmpfile.path
|
90
81
|
}
|
91
82
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
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)
|
@@ -3,40 +3,40 @@ module ActiveSupport
|
|
3
3
|
module Stream #:nodoc:
|
4
4
|
private
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
31
|
+
yield
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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 =
|
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
|
-
|
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[
|
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 |
|
29
|
-
|
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.
|
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.
|
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.
|
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
|
data/lib/active_support/time.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
module ActiveSupport
|
2
|
-
autoload :Duration,
|
3
|
-
autoload :TimeWithZone,
|
4
|
-
autoload :TimeZone,
|
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
|
8
|
-
require
|
7
|
+
require "date"
|
8
|
+
require "time"
|
9
9
|
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
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
|
15
|
-
require
|
14
|
+
require "active_support/core_ext/integer/time"
|
15
|
+
require "active_support/core_ext/numeric/time"
|
16
16
|
|
17
|
-
require
|
18
|
-
require
|
17
|
+
require "active_support/core_ext/string/conversions"
|
18
|
+
require "active_support/core_ext/string/zones"
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
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
|
-
|
41
|
+
"Time"
|
43
42
|
end
|
44
43
|
|
45
44
|
PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N".freeze }
|
46
|
-
PRECISIONS[0] =
|
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[
|
174
|
+
initialize(coder["utc"], coder["zone"], coder["time"])
|
175
175
|
end
|
176
176
|
|
177
177
|
def encode_with(coder) #:nodoc:
|
178
|
-
coder.tag =
|
179
|
-
coder.map = {
|
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,
|
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
|
2
|
-
require
|
3
|
-
require
|
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 =
|
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
|
-
|
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
|
-
|
236
|
-
|
237
|
-
|
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
|
-
|
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[
|
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 = {
|
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
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
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)
|