activesupport 5.0.7.2 → 5.1.0.beta1
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 +5 -5
- data/CHANGELOG.md +215 -820
- 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 +42 -49
- data/lib/active_support/cache/file_store.rb +12 -21
- data/lib/active_support/cache/mem_cache_store.rb +30 -40
- data/lib/active_support/cache/memory_store.rb +11 -13
- data/lib/active_support/cache/null_store.rb +4 -4
- data/lib/active_support/cache/strategy/local_cache.rb +16 -25
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +8 -9
- data/lib/active_support/callbacks.rb +647 -584
- 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 +9 -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 +9 -9
- data/lib/active_support/core_ext/date_time/compatibility.rb +2 -13
- 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 +46 -57
- 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 +8 -8
- 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/marshal.rb +2 -2
- 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 +82 -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 +24 -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 +4 -4
- data/lib/active_support/core_ext/object/try.rb +1 -1
- data/lib/active_support/core_ext/object/with_options.rb +1 -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 +23 -29
- data/lib/active_support/core_ext/time/compatibility.rb +1 -10
- data/lib/active_support/core_ext/time/conversions.rb +12 -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 -47
- data/lib/active_support/dependencies/interlock.rb +1 -1
- data/lib/active_support/deprecation.rb +8 -8
- data/lib/active_support/deprecation/behaviors.rb +3 -3
- data/lib/active_support/deprecation/instance_delegator.rb +2 -2
- data/lib/active_support/deprecation/method_wrappers.rb +3 -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 +30 -26
- 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 -60
- 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 +3 -3
- data/lib/active_support/gzip.rb +5 -5
- data/lib/active_support/hash_with_indifferent_access.rb +10 -20
- data/lib/active_support/i18n.rb +5 -5
- data/lib/active_support/i18n_railtie.rb +11 -10
- 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 +51 -50
- 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 +12 -30
- data/lib/active_support/log_subscriber.rb +5 -5
- 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 +72 -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 +5 -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 +4 -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 +6 -6
- 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 +6 -6
- 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 +8 -14
- 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 +6 -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 +13 -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 -12
- data/lib/active_support/time.rb +12 -12
- data/lib/active_support/time_with_zone.rb +16 -26
- data/lib/active_support/values/time_zone.rb +40 -46
- 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 +15 -12
- data/lib/active_support/xml_mini/libxmlsax.rb +17 -15
- data/lib/active_support/xml_mini/nokogiri.rb +13 -11
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -14
- data/lib/active_support/xml_mini/rexml.rb +9 -9
- metadata +8 -19
- 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
@@ -2,7 +2,7 @@ require "active_support/notifications"
|
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
4
|
# Raised when <tt>ActiveSupport::Deprecation::Behavior#behavior</tt> is set with <tt>:raise</tt>.
|
5
|
-
# You would set <tt>:raise</tt>, as a
|
5
|
+
# You would set <tt>:raise</tt>, as a behavior to raise errors and proactively report exceptions from deprecations.
|
6
6
|
class DeprecationException < StandardError
|
7
7
|
end
|
8
8
|
|
@@ -25,7 +25,7 @@ module ActiveSupport
|
|
25
25
|
if defined?(Rails.logger) && Rails.logger
|
26
26
|
Rails.logger
|
27
27
|
else
|
28
|
-
require
|
28
|
+
require "active_support/logger"
|
29
29
|
ActiveSupport::Logger.new($stderr)
|
30
30
|
end
|
31
31
|
logger.warn message
|
@@ -34,7 +34,7 @@ module ActiveSupport
|
|
34
34
|
|
35
35
|
notify: ->(message, callstack) {
|
36
36
|
ActiveSupport::Notifications.instrument("deprecation.rails",
|
37
|
-
:
|
37
|
+
message: message, callstack: callstack)
|
38
38
|
},
|
39
39
|
|
40
40
|
silence: ->(message, callstack) {},
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/core_ext/kernel/singleton_class"
|
2
|
+
require "active_support/core_ext/module/delegation"
|
3
3
|
|
4
4
|
module ActiveSupport
|
5
5
|
class Deprecation
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/core_ext/module/aliasing"
|
2
|
+
require "active_support/core_ext/array/extract_options"
|
3
3
|
|
4
4
|
module ActiveSupport
|
5
5
|
class Deprecation
|
@@ -18,7 +18,7 @@ module ActiveSupport
|
|
18
18
|
#
|
19
19
|
# Using the default deprecator:
|
20
20
|
# ActiveSupport::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
|
21
|
-
# # =>
|
21
|
+
# # => Fred
|
22
22
|
#
|
23
23
|
# Fred.aaa
|
24
24
|
# # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.1. (called from irb_binding at (irb):10)
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/inflector/methods"
|
2
|
+
require "active_support/core_ext/regexp"
|
2
3
|
|
3
4
|
module ActiveSupport
|
4
5
|
class Deprecation
|
@@ -10,7 +11,7 @@ module ActiveSupport
|
|
10
11
|
super
|
11
12
|
end
|
12
13
|
|
13
|
-
instance_methods.each { |m| undef_method m unless
|
14
|
+
instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
|
14
15
|
|
15
16
|
# Don't give a deprecation warning on inspect since test/unit and error
|
16
17
|
# logs rely on it for diagnostics.
|
@@ -121,10 +122,11 @@ module ActiveSupport
|
|
121
122
|
# (Backtrace information…)
|
122
123
|
# ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
|
123
124
|
class DeprecatedConstantProxy < DeprecationProxy
|
124
|
-
def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance)
|
125
|
+
def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
|
125
126
|
@old_const = old_const
|
126
127
|
@new_const = new_const
|
127
128
|
@deprecator = deprecator
|
129
|
+
@message = message
|
128
130
|
end
|
129
131
|
|
130
132
|
# Returns the class of the new constant.
|
@@ -142,7 +144,7 @@ module ActiveSupport
|
|
142
144
|
end
|
143
145
|
|
144
146
|
def warn(callstack, called, args)
|
145
|
-
@deprecator.warn(
|
147
|
+
@deprecator.warn(@message, callstack)
|
146
148
|
end
|
147
149
|
end
|
148
150
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "rbconfig"
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
4
|
class Deprecation
|
@@ -48,17 +48,17 @@ module ActiveSupport
|
|
48
48
|
private
|
49
49
|
# Outputs a deprecation warning message
|
50
50
|
#
|
51
|
-
#
|
51
|
+
# deprecated_method_warning(:method_name)
|
52
52
|
# # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon}"
|
53
|
-
#
|
53
|
+
# deprecated_method_warning(:method_name, :another_method)
|
54
54
|
# # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (use another_method instead)"
|
55
|
-
#
|
55
|
+
# deprecated_method_warning(:method_name, "Optional message")
|
56
56
|
# # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (Optional message)"
|
57
57
|
def deprecated_method_warning(method_name, message = nil)
|
58
58
|
warning = "#{method_name} is deprecated and will be removed from #{gem_name} #{deprecation_horizon}"
|
59
59
|
case message
|
60
|
-
|
61
|
-
|
60
|
+
when Symbol then "#{warning} (use #{message} instead)"
|
61
|
+
when String then "#{warning} (#{message})"
|
62
62
|
else warning
|
63
63
|
end
|
64
64
|
end
|
@@ -105,7 +105,7 @@ module ActiveSupport
|
|
105
105
|
RAILS_GEM_ROOT = File.expand_path("../../../../..", __FILE__) + "/"
|
106
106
|
|
107
107
|
def ignored_callstack(path)
|
108
|
-
path.start_with?(RAILS_GEM_ROOT) || path.start_with?(RbConfig::CONFIG[
|
108
|
+
path.start_with?(RAILS_GEM_ROOT) || path.start_with?(RbConfig::CONFIG["rubylibdir"])
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/core_ext/array/conversions"
|
2
|
+
require "active_support/core_ext/object/acts_like"
|
3
3
|
|
4
4
|
module ActiveSupport
|
5
5
|
# Provides accurate date and time measurements using Date#advance and
|
@@ -11,8 +11,8 @@ module ActiveSupport
|
|
11
11
|
SECONDS_PER_HOUR = 3600
|
12
12
|
SECONDS_PER_DAY = 86400
|
13
13
|
SECONDS_PER_WEEK = 604800
|
14
|
-
SECONDS_PER_MONTH =
|
15
|
-
SECONDS_PER_YEAR =
|
14
|
+
SECONDS_PER_MONTH = 2629746 # 1/12 of a gregorian year
|
15
|
+
SECONDS_PER_YEAR = 31556952 # length of a gregorian year (365.2425 days)
|
16
16
|
|
17
17
|
PARTS_IN_SECONDS = {
|
18
18
|
seconds: 1,
|
@@ -26,8 +26,8 @@ module ActiveSupport
|
|
26
26
|
|
27
27
|
attr_accessor :value, :parts
|
28
28
|
|
29
|
-
autoload :ISO8601Parser,
|
30
|
-
autoload :ISO8601Serializer,
|
29
|
+
autoload :ISO8601Parser, "active_support/duration/iso8601_parser"
|
30
|
+
autoload :ISO8601Serializer, "active_support/duration/iso8601_serializer"
|
31
31
|
|
32
32
|
class << self
|
33
33
|
# Creates a new Duration from string formatted according to ISO 8601 Duration.
|
@@ -84,16 +84,22 @@ module ActiveSupport
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def initialize(value, parts) #:nodoc:
|
87
|
-
@value, @parts = value, parts
|
87
|
+
@value, @parts = value, parts.to_h
|
88
|
+
@parts.default = 0
|
88
89
|
end
|
89
90
|
|
90
91
|
# Adds another Duration or a Numeric to this Duration. Numeric values
|
91
92
|
# are treated as seconds.
|
92
93
|
def +(other)
|
93
94
|
if Duration === other
|
94
|
-
|
95
|
+
parts = @parts.dup
|
96
|
+
other.parts.each do |(key, value)|
|
97
|
+
parts[key] += value
|
98
|
+
end
|
99
|
+
Duration.new(value + other.value, parts)
|
95
100
|
else
|
96
|
-
|
101
|
+
seconds = @parts[:seconds] + other
|
102
|
+
Duration.new(value + other, @parts.merge(seconds: seconds))
|
97
103
|
end
|
98
104
|
end
|
99
105
|
|
@@ -104,7 +110,7 @@ module ActiveSupport
|
|
104
110
|
end
|
105
111
|
|
106
112
|
def -@ #:nodoc:
|
107
|
-
Duration.new(-value, parts.map { |type,number| [type, -number] })
|
113
|
+
Duration.new(-value, parts.map { |type, number| [type, -number] })
|
108
114
|
end
|
109
115
|
|
110
116
|
def is_a?(klass) #:nodoc:
|
@@ -141,14 +147,14 @@ module ActiveSupport
|
|
141
147
|
# 1.day.to_i # => 86400
|
142
148
|
#
|
143
149
|
# Note that this conversion makes some assumptions about the
|
144
|
-
# duration of some periods, e.g. months are always
|
145
|
-
# and years are 365.
|
150
|
+
# duration of some periods, e.g. months are always 1/12 of year
|
151
|
+
# and years are 365.2425 days:
|
146
152
|
#
|
147
|
-
# # equivalent to
|
148
|
-
# 1.month.to_i # =>
|
153
|
+
# # equivalent to (1.year / 12).to_i
|
154
|
+
# 1.month.to_i # => 2629746
|
149
155
|
#
|
150
|
-
# # equivalent to 365.
|
151
|
-
# 1.year.to_i # =>
|
156
|
+
# # equivalent to 365.2425.days.to_i
|
157
|
+
# 1.year.to_i # => 31556952
|
152
158
|
#
|
153
159
|
# In such cases, Ruby's core
|
154
160
|
# Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
|
@@ -184,9 +190,9 @@ module ActiveSupport
|
|
184
190
|
|
185
191
|
def inspect #:nodoc:
|
186
192
|
parts.
|
187
|
-
reduce(::Hash.new(0)) { |h,(l,r)| h[l] += r; h }.
|
188
|
-
sort_by {|unit, _ | [:years, :months, :weeks, :days, :hours, :minutes, :seconds].index(unit)}.
|
189
|
-
map {|unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}"}.
|
193
|
+
reduce(::Hash.new(0)) { |h, (l, r)| h[l] += r; h }.
|
194
|
+
sort_by { |unit, _ | [:years, :months, :weeks, :days, :hours, :minutes, :seconds].index(unit) }.
|
195
|
+
map { |unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}" }.
|
190
196
|
to_sentence(locale: ::I18n.default_locale)
|
191
197
|
end
|
192
198
|
|
@@ -194,7 +200,7 @@ module ActiveSupport
|
|
194
200
|
to_i
|
195
201
|
end
|
196
202
|
|
197
|
-
def respond_to_missing?(method, include_private=false) #:nodoc:
|
203
|
+
def respond_to_missing?(method, include_private = false) #:nodoc:
|
198
204
|
@value.respond_to?(method, include_private)
|
199
205
|
end
|
200
206
|
|
@@ -206,10 +212,10 @@ module ActiveSupport
|
|
206
212
|
|
207
213
|
delegate :<=>, to: :value
|
208
214
|
|
209
|
-
|
215
|
+
private
|
210
216
|
|
211
|
-
def sum(sign, time = ::Time.current)
|
212
|
-
parts.inject(time) do |t,(type,number)|
|
217
|
+
def sum(sign, time = ::Time.current)
|
218
|
+
parts.inject(time) do |t, (type, number)|
|
213
219
|
if t.acts_like?(:time) || t.acts_like?(:date)
|
214
220
|
if type == :seconds
|
215
221
|
t.since(sign * number)
|
@@ -226,9 +232,7 @@ module ActiveSupport
|
|
226
232
|
end
|
227
233
|
end
|
228
234
|
|
229
|
-
|
230
|
-
|
231
|
-
def method_missing(method, *args, &block) #:nodoc:
|
235
|
+
def method_missing(method, *args, &block)
|
232
236
|
value.send(method, *args, &block)
|
233
237
|
end
|
234
238
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require "strscan"
|
2
|
+
require "active_support/core_ext/regexp"
|
2
3
|
|
3
4
|
module ActiveSupport
|
4
5
|
class Duration
|
@@ -11,8 +12,8 @@ module ActiveSupport
|
|
11
12
|
class ParsingError < ::ArgumentError; end
|
12
13
|
|
13
14
|
PERIOD_OR_COMMA = /\.|,/
|
14
|
-
PERIOD =
|
15
|
-
COMMA =
|
15
|
+
PERIOD = ".".freeze
|
16
|
+
COMMA = ",".freeze
|
16
17
|
|
17
18
|
SIGN_MARKER = /\A\-|\+|/
|
18
19
|
DATE_MARKER = /P/
|
@@ -20,8 +21,8 @@ module ActiveSupport
|
|
20
21
|
DATE_COMPONENT = /(\-?\d+(?:[.,]\d+)?)(Y|M|D|W)/
|
21
22
|
TIME_COMPONENT = /(\-?\d+(?:[.,]\d+)?)(H|M|S)/
|
22
23
|
|
23
|
-
DATE_TO_PART = {
|
24
|
-
TIME_TO_PART = {
|
24
|
+
DATE_TO_PART = { "Y" => :years, "M" => :months, "W" => :weeks, "D" => :days }
|
25
|
+
TIME_TO_PART = { "H" => :hours, "M" => :minutes, "S" => :seconds }
|
25
26
|
|
26
27
|
DATE_COMPONENTS = [:years, :months, :days]
|
27
28
|
TIME_COMPONENTS = [:hours, :minutes, :seconds]
|
@@ -39,36 +40,36 @@ module ActiveSupport
|
|
39
40
|
def parse!
|
40
41
|
while !finished?
|
41
42
|
case mode
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
43
|
+
when :start
|
44
|
+
if scan(SIGN_MARKER)
|
45
|
+
self.sign = (scanner.matched == "-") ? -1 : 1
|
46
|
+
self.mode = :sign
|
47
|
+
else
|
48
|
+
raise_parsing_error
|
49
|
+
end
|
50
|
+
|
51
|
+
when :sign
|
52
|
+
if scan(DATE_MARKER)
|
53
|
+
self.mode = :date
|
54
|
+
else
|
55
|
+
raise_parsing_error
|
56
|
+
end
|
57
|
+
|
58
|
+
when :date
|
59
|
+
if scan(TIME_MARKER)
|
60
|
+
self.mode = :time
|
61
|
+
elsif scan(DATE_COMPONENT)
|
62
|
+
parts[DATE_TO_PART[scanner[2]]] = number * sign
|
63
|
+
else
|
64
|
+
raise_parsing_error
|
65
|
+
end
|
66
|
+
|
67
|
+
when :time
|
68
|
+
if scan(TIME_COMPONENT)
|
69
|
+
parts[TIME_TO_PART[scanner[2]]] = number * sign
|
70
|
+
else
|
71
|
+
raise_parsing_error
|
72
|
+
end
|
72
73
|
|
73
74
|
end
|
74
75
|
end
|
@@ -79,44 +80,44 @@ module ActiveSupport
|
|
79
80
|
|
80
81
|
private
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
def finished?
|
84
|
+
scanner.eos?
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
# Parses number which can be a float with either comma or period.
|
88
|
+
def number
|
89
|
+
PERIOD_OR_COMMA.match?(scanner[1]) ? scanner[1].tr(COMMA, PERIOD).to_f : scanner[1].to_i
|
90
|
+
end
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
92
|
+
def scan(pattern)
|
93
|
+
scanner.scan(pattern)
|
94
|
+
end
|
94
95
|
|
95
|
-
|
96
|
-
|
97
|
-
|
96
|
+
def raise_parsing_error(reason = nil)
|
97
|
+
raise ParsingError, "Invalid ISO 8601 duration: #{scanner.string.inspect} #{reason}".strip
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
100
|
+
# Checks for various semantic errors as stated in ISO 8601 standard.
|
101
|
+
def validate!
|
102
|
+
raise_parsing_error("is empty duration") if parts.empty?
|
102
103
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
104
|
+
# Mixing any of Y, M, D with W is invalid.
|
105
|
+
if parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any?
|
106
|
+
raise_parsing_error("mixing weeks with other date parts not allowed")
|
107
|
+
end
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
# Specifying an empty T part is invalid.
|
110
|
+
if mode == :time && (parts.keys & TIME_COMPONENTS).empty?
|
111
|
+
raise_parsing_error("time part marker is present but time part is empty")
|
112
|
+
end
|
112
113
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
114
|
+
fractions = parts.values.reject(&:zero?).select { |a| (a % 1) != 0 }
|
115
|
+
unless fractions.empty? || (fractions.size == 1 && fractions.last == @parts.values.reject(&:zero?).last)
|
116
|
+
raise_parsing_error "(only last part can be fractional)"
|
117
|
+
end
|
117
118
|
|
118
|
-
|
119
|
-
|
119
|
+
return true
|
120
|
+
end
|
120
121
|
end
|
121
122
|
end
|
122
123
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/core_ext/object/blank"
|
2
|
+
require "active_support/core_ext/hash/transform_values"
|
3
3
|
|
4
4
|
module ActiveSupport
|
5
5
|
class Duration
|
6
6
|
# Serializes duration to string according to ISO 8601 Duration format.
|
7
|
-
class ISO8601Serializer
|
7
|
+
class ISO8601Serializer # :nodoc:
|
8
8
|
def initialize(duration, precision: nil)
|
9
9
|
@duration = duration
|
10
10
|
@precision = precision
|
@@ -12,19 +12,21 @@ module ActiveSupport
|
|
12
12
|
|
13
13
|
# Builds and returns output string.
|
14
14
|
def serialize
|
15
|
-
output = 'P'
|
16
15
|
parts, sign = normalize
|
16
|
+
return "PT0S".freeze if parts.empty?
|
17
|
+
|
18
|
+
output = "P"
|
17
19
|
output << "#{parts[:years]}Y" if parts.key?(:years)
|
18
20
|
output << "#{parts[:months]}M" if parts.key?(:months)
|
19
21
|
output << "#{parts[:weeks]}W" if parts.key?(:weeks)
|
20
22
|
output << "#{parts[:days]}D" if parts.key?(:days)
|
21
|
-
time =
|
23
|
+
time = ""
|
22
24
|
time << "#{parts[:hours]}H" if parts.key?(:hours)
|
23
25
|
time << "#{parts[:minutes]}M" if parts.key?(:minutes)
|
24
26
|
if parts.key?(:seconds)
|
25
27
|
time << "#{sprintf(@precision ? "%0.0#{@precision}f" : '%g', parts[:seconds])}S"
|
26
28
|
end
|
27
|
-
output << "T#{time}"
|
29
|
+
output << "T#{time}" unless time.empty?
|
28
30
|
"#{sign}#{output}"
|
29
31
|
end
|
30
32
|
|
@@ -35,13 +37,13 @@ module ActiveSupport
|
|
35
37
|
# Zero parts are removed as not significant.
|
36
38
|
# If all parts are negative it will negate all of them and return minus as a sign.
|
37
39
|
def normalize
|
38
|
-
parts = @duration.parts.each_with_object(Hash.new(0)) do |(k,v),p|
|
40
|
+
parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
|
39
41
|
p[k] += v unless v.zero?
|
40
42
|
end
|
41
43
|
# If all parts are negative - let's make a negative duration
|
42
|
-
sign =
|
44
|
+
sign = ""
|
43
45
|
if parts.values.all? { |v| v < 0 }
|
44
|
-
sign =
|
46
|
+
sign = "-"
|
45
47
|
parts.transform_values!(&:-@)
|
46
48
|
end
|
47
49
|
[parts, sign]
|