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,4 +1,4 @@
1
- require 'active_support/concurrency/share_lock'
1
+ require "active_support/concurrency/share_lock"
2
2
 
3
3
  module ActiveSupport #:nodoc:
4
4
  module Dependencies #:nodoc:
@@ -1,4 +1,4 @@
1
- require 'singleton'
1
+ require "singleton"
2
2
 
3
3
  module ActiveSupport
4
4
  # \Deprecation specifies the API used by Rails to deprecate methods, instance
@@ -12,12 +12,13 @@ module ActiveSupport
12
12
  # a circular require warning for active_support/deprecation.rb.
13
13
  #
14
14
  # So, we define the constant first, and load dependencies later.
15
- require 'active_support/deprecation/instance_delegator'
16
- require 'active_support/deprecation/behaviors'
17
- require 'active_support/deprecation/reporting'
18
- require 'active_support/deprecation/method_wrappers'
19
- require 'active_support/deprecation/proxy_wrappers'
20
- require 'active_support/core_ext/module/deprecation'
15
+ require "active_support/deprecation/instance_delegator"
16
+ require "active_support/deprecation/behaviors"
17
+ require "active_support/deprecation/reporting"
18
+ require "active_support/deprecation/constant_accessor"
19
+ require "active_support/deprecation/method_wrappers"
20
+ require "active_support/deprecation/proxy_wrappers"
21
+ require "active_support/core_ext/module/deprecation"
21
22
 
22
23
  include Singleton
23
24
  include InstanceDelegator
@@ -32,7 +33,7 @@ module ActiveSupport
32
33
  # and the second is a library name
33
34
  #
34
35
  # ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
35
- def initialize(deprecation_horizon = '5.1', gem_name = 'Rails')
36
+ def initialize(deprecation_horizon = "5.2", gem_name = "Rails")
36
37
  self.gem_name = gem_name
37
38
  self.deprecation_horizon = deprecation_horizon
38
39
  # By default, warnings are not silenced and debugging is off.
@@ -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 behaviour to raise errors and proactively report exceptions from deprecations.
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 'active_support/logger'
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
- :message => message, :callstack => callstack)
37
+ message: message, callstack: callstack)
38
38
  },
39
39
 
40
40
  silence: ->(message, callstack) {},
@@ -0,0 +1,50 @@
1
+ require "active_support/inflector/methods"
2
+
3
+ module ActiveSupport
4
+ class Deprecation
5
+ # DeprecatedConstantAccessor transforms a constant into a deprecated one by
6
+ # hooking +const_missing+.
7
+ #
8
+ # It takes the names of an old (deprecated) constant and of a new constant
9
+ # (both in string form) and optionally a deprecator. The deprecator defaults
10
+ # to +ActiveSupport::Deprecator+ if none is specified.
11
+ #
12
+ # The deprecated constant now returns the same object as the new one rather
13
+ # than a proxy object, so it can be used transparently in +rescue+ blocks
14
+ # etc.
15
+ #
16
+ # PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
17
+ #
18
+ # (In a later update, the original implementation of `PLANETS` has been removed.)
19
+ #
20
+ # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
21
+ # include ActiveSupport::Deprecation::DeprecatedConstantAccessor
22
+ # deprecate_constant 'PLANETS', 'PLANETS_POST_2006'
23
+ #
24
+ # PLANETS.map { |planet| planet.capitalize }
25
+ # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
26
+ # (Backtrace information…)
27
+ # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
28
+ module DeprecatedConstantAccessor
29
+ def self.included(base)
30
+ extension = Module.new do
31
+ def const_missing(missing_const_name)
32
+ if class_variable_defined?(:@@_deprecated_constants)
33
+ if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
34
+ replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", caller_locations)
35
+ return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
36
+ end
37
+ end
38
+ super
39
+ end
40
+
41
+ def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
42
+ class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
43
+ class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
44
+ end
45
+ end
46
+ base.singleton_class.prepend extension
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,5 +1,5 @@
1
- require 'active_support/core_ext/kernel/singleton_class'
2
- require 'active_support/core_ext/module/delegation'
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 'active_support/core_ext/module/aliasing'
2
- require 'active_support/core_ext/array/extract_options'
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
- # # => [:aaa, :bbb, :ccc]
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)
@@ -60,6 +60,13 @@ module ActiveSupport
60
60
  deprecator.deprecation_warning(method_name, options[method_name])
61
61
  super(*args, &block)
62
62
  end
63
+
64
+ case
65
+ when target_module.protected_method_defined?(method_name)
66
+ protected method_name
67
+ when target_module.private_method_defined?(method_name)
68
+ private method_name
69
+ end
63
70
  end
64
71
  end
65
72
 
@@ -1,4 +1,5 @@
1
- require 'active_support/inflector/methods'
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 m =~ /^__|^object_id$/ }
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("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
147
+ @deprecator.warn(@message, callstack)
146
148
  end
147
149
  end
148
150
  end
@@ -1,4 +1,4 @@
1
- require 'rbconfig'
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
- # ActiveSupport::Deprecation.deprecated_method_warning(:method_name)
51
+ # deprecated_method_warning(:method_name)
52
52
  # # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon}"
53
- # ActiveSupport::Deprecation.deprecated_method_warning(:method_name, :another_method)
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
- # ActiveSupport::Deprecation.deprecated_method_warning(:method_name, "Optional message")
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
- when Symbol then "#{warning} (use #{message} instead)"
61
- when String then "#{warning} (#{message})"
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['rubylibdir'])
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,8 @@
1
- require 'active_support/core_ext/array/conversions'
2
- require 'active_support/core_ext/object/acts_like'
1
+ require "active_support/core_ext/array/conversions"
2
+ require "active_support/core_ext/module/delegation"
3
+ require "active_support/core_ext/object/acts_like"
4
+ require "active_support/core_ext/string/filters"
5
+ require "active_support/deprecation"
3
6
 
4
7
  module ActiveSupport
5
8
  # Provides accurate date and time measurements using Date#advance and
@@ -7,12 +10,106 @@ module ActiveSupport
7
10
  #
8
11
  # 1.month.ago # equivalent to Time.now.advance(months: -1)
9
12
  class Duration
13
+ class Scalar < Numeric #:nodoc:
14
+ attr_reader :value
15
+ delegate :to_i, :to_f, :to_s, to: :value
16
+
17
+ def initialize(value)
18
+ @value = value
19
+ end
20
+
21
+ def coerce(other)
22
+ [Scalar.new(other), self]
23
+ end
24
+
25
+ def -@
26
+ Scalar.new(-value)
27
+ end
28
+
29
+ def <=>(other)
30
+ if Scalar === other || Duration === other
31
+ value <=> other.value
32
+ elsif Numeric === other
33
+ value <=> other
34
+ else
35
+ nil
36
+ end
37
+ end
38
+
39
+ def +(other)
40
+ if Duration === other
41
+ seconds = value + other.parts[:seconds]
42
+ new_parts = other.parts.merge(seconds: seconds)
43
+ new_value = value + other.value
44
+
45
+ Duration.new(new_value, new_parts)
46
+ else
47
+ calculate(:+, other)
48
+ end
49
+ end
50
+
51
+ def -(other)
52
+ if Duration === other
53
+ seconds = value - other.parts[:seconds]
54
+ new_parts = other.parts.map { |part, other_value| [part, -other_value] }.to_h
55
+ new_parts = new_parts.merge(seconds: seconds)
56
+ new_value = value - other.value
57
+
58
+ Duration.new(new_value, new_parts)
59
+ else
60
+ calculate(:-, other)
61
+ end
62
+ end
63
+
64
+ def *(other)
65
+ if Duration === other
66
+ new_parts = other.parts.map { |part, other_value| [part, value * other_value] }.to_h
67
+ new_value = value * other.value
68
+
69
+ Duration.new(new_value, new_parts)
70
+ else
71
+ calculate(:*, other)
72
+ end
73
+ end
74
+
75
+ def /(other)
76
+ if Duration === other
77
+ value / other.value
78
+ else
79
+ calculate(:/, other)
80
+ end
81
+ end
82
+
83
+ def %(other)
84
+ if Duration === other
85
+ Duration.build(value % other.value)
86
+ else
87
+ calculate(:%, other)
88
+ end
89
+ end
90
+
91
+ private
92
+ def calculate(op, other)
93
+ if Scalar === other
94
+ Scalar.new(value.public_send(op, other.value))
95
+ elsif Numeric === other
96
+ Scalar.new(value.public_send(op, other))
97
+ else
98
+ raise_type_error(other)
99
+ end
100
+ end
101
+
102
+ def raise_type_error(other)
103
+ raise TypeError, "no implicit conversion of #{other.class} into #{self.class}"
104
+ end
105
+ end
106
+
10
107
  SECONDS_PER_MINUTE = 60
11
108
  SECONDS_PER_HOUR = 3600
12
109
  SECONDS_PER_DAY = 86400
13
110
  SECONDS_PER_WEEK = 604800
14
- SECONDS_PER_MONTH = 2592000 # 30 days
15
- SECONDS_PER_YEAR = 31557600 # length of a julian year (365.2425 days)
111
+ SECONDS_PER_MONTH = 2629746 # 1/12 of a gregorian year
112
+ SECONDS_PER_YEAR = 31556952 # length of a gregorian year (365.2425 days)
16
113
 
17
114
  PARTS_IN_SECONDS = {
18
115
  seconds: 1,
@@ -24,10 +121,12 @@ module ActiveSupport
24
121
  years: SECONDS_PER_YEAR
25
122
  }.freeze
26
123
 
124
+ PARTS = [:years, :months, :weeks, :days, :hours, :minutes, :seconds].freeze
125
+
27
126
  attr_accessor :value, :parts
28
127
 
29
- autoload :ISO8601Parser, 'active_support/duration/iso8601_parser'
30
- autoload :ISO8601Serializer, 'active_support/duration/iso8601_serializer'
128
+ autoload :ISO8601Parser, "active_support/duration/iso8601_parser"
129
+ autoload :ISO8601Serializer, "active_support/duration/iso8601_serializer"
31
130
 
32
131
  class << self
33
132
  # Creates a new Duration from string formatted according to ISO 8601 Duration.
@@ -74,6 +173,30 @@ module ActiveSupport
74
173
  new(value * SECONDS_PER_YEAR, [[:years, value]])
75
174
  end
76
175
 
176
+ # Creates a new Duration from a seconds value that is converted
177
+ # to the individual parts:
178
+ #
179
+ # ActiveSupport::Duration.build(31556952).parts # => {:years=>1}
180
+ # ActiveSupport::Duration.build(2716146).parts # => {:months=>1, :days=>1}
181
+ #
182
+ def build(value)
183
+ parts = {}
184
+ remainder = value.to_f
185
+
186
+ PARTS.each do |part|
187
+ unless part == :seconds
188
+ part_in_seconds = PARTS_IN_SECONDS[part]
189
+ parts[part] = remainder.div(part_in_seconds)
190
+ remainder = (remainder % part_in_seconds).round(9)
191
+ end
192
+ end
193
+
194
+ parts[:seconds] = remainder
195
+ parts.reject! { |k, v| v.zero? }
196
+
197
+ new(value, parts)
198
+ end
199
+
77
200
  private
78
201
 
79
202
  def calculate_total_seconds(parts)
@@ -84,16 +207,40 @@ module ActiveSupport
84
207
  end
85
208
 
86
209
  def initialize(value, parts) #:nodoc:
87
- @value, @parts = value, parts
210
+ @value, @parts = value, parts.to_h
211
+ @parts.default = 0
212
+ end
213
+
214
+ def coerce(other) #:nodoc:
215
+ if Scalar === other
216
+ [other, self]
217
+ else
218
+ [Scalar.new(other), self]
219
+ end
220
+ end
221
+
222
+ # Compares one Duration with another or a Numeric to this Duration.
223
+ # Numeric values are treated as seconds.
224
+ def <=>(other)
225
+ if Duration === other
226
+ value <=> other.value
227
+ elsif Numeric === other
228
+ value <=> other
229
+ end
88
230
  end
89
231
 
90
232
  # Adds another Duration or a Numeric to this Duration. Numeric values
91
233
  # are treated as seconds.
92
234
  def +(other)
93
235
  if Duration === other
94
- Duration.new(value + other.value, @parts + other.parts)
236
+ parts = @parts.dup
237
+ other.parts.each do |(key, value)|
238
+ parts[key] += value
239
+ end
240
+ Duration.new(value + other.value, parts)
95
241
  else
96
- Duration.new(value + other, @parts + [[:seconds, other]])
242
+ seconds = @parts[:seconds] + other
243
+ Duration.new(value + other, @parts.merge(seconds: seconds))
97
244
  end
98
245
  end
99
246
 
@@ -103,8 +250,44 @@ module ActiveSupport
103
250
  self + (-other)
104
251
  end
105
252
 
253
+ # Multiplies this Duration by a Numeric and returns a new Duration.
254
+ def *(other)
255
+ if Scalar === other || Duration === other
256
+ Duration.new(value * other.value, parts.map { |type, number| [type, number * other.value] })
257
+ elsif Numeric === other
258
+ Duration.new(value * other, parts.map { |type, number| [type, number * other] })
259
+ else
260
+ raise_type_error(other)
261
+ end
262
+ end
263
+
264
+ # Divides this Duration by a Numeric and returns a new Duration.
265
+ def /(other)
266
+ if Scalar === other
267
+ Duration.new(value / other.value, parts.map { |type, number| [type, number / other.value] })
268
+ elsif Duration === other
269
+ value / other.value
270
+ elsif Numeric === other
271
+ Duration.new(value / other, parts.map { |type, number| [type, number / other] })
272
+ else
273
+ raise_type_error(other)
274
+ end
275
+ end
276
+
277
+ # Returns the modulo of this Duration by another Duration or Numeric.
278
+ # Numeric values are treated as seconds.
279
+ def %(other)
280
+ if Duration === other || Scalar === other
281
+ Duration.build(value % other.value)
282
+ elsif Numeric === other
283
+ Duration.build(value % other)
284
+ else
285
+ raise_type_error(other)
286
+ end
287
+ end
288
+
106
289
  def -@ #:nodoc:
107
- Duration.new(-value, parts.map { |type,number| [type, -number] })
290
+ Duration.new(-value, parts.map { |type, number| [type, -number] })
108
291
  end
109
292
 
110
293
  def is_a?(klass) #:nodoc:
@@ -141,14 +324,14 @@ module ActiveSupport
141
324
  # 1.day.to_i # => 86400
142
325
  #
143
326
  # Note that this conversion makes some assumptions about the
144
- # duration of some periods, e.g. months are always 30 days
145
- # and years are 365.25 days:
327
+ # duration of some periods, e.g. months are always 1/12 of year
328
+ # and years are 365.2425 days:
146
329
  #
147
- # # equivalent to 30.days.to_i
148
- # 1.month.to_i # => 2592000
330
+ # # equivalent to (1.year / 12).to_i
331
+ # 1.month.to_i # => 2629746
149
332
  #
150
- # # equivalent to 365.25.days.to_i
151
- # 1.year.to_i # => 31557600
333
+ # # equivalent to 365.2425.days.to_i
334
+ # 1.year.to_i # => 31556952
152
335
  #
153
336
  # In such cases, Ruby's core
154
337
  # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
@@ -174,6 +357,7 @@ module ActiveSupport
174
357
  sum(1, time)
175
358
  end
176
359
  alias :from_now :since
360
+ alias :after :since
177
361
 
178
362
  # Calculates a new Time or Date that is as far in the past
179
363
  # as this Duration represents.
@@ -181,12 +365,13 @@ module ActiveSupport
181
365
  sum(-1, time)
182
366
  end
183
367
  alias :until :ago
368
+ alias :before :ago
184
369
 
185
370
  def inspect #:nodoc:
186
371
  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}"}.
372
+ reduce(::Hash.new(0)) { |h, (l, r)| h[l] += r; h }.
373
+ sort_by { |unit, _ | PARTS.index(unit) }.
374
+ map { |unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}" }.
190
375
  to_sentence(locale: ::I18n.default_locale)
191
376
  end
192
377
 
@@ -194,22 +379,28 @@ module ActiveSupport
194
379
  to_i
195
380
  end
196
381
 
197
- def respond_to_missing?(method, include_private=false) #:nodoc:
382
+ def respond_to_missing?(method, include_private = false) #:nodoc:
198
383
  @value.respond_to?(method, include_private)
199
384
  end
200
385
 
386
+ def init_with(coder) #:nodoc:
387
+ initialize(coder["value"], coder["parts"])
388
+ end
389
+
390
+ def encode_with(coder) #:nodoc:
391
+ coder.map = { "value" => @value, "parts" => @parts }
392
+ end
393
+
201
394
  # Build ISO 8601 Duration string for this duration.
202
395
  # The +precision+ parameter can be used to limit seconds' precision of duration.
203
396
  def iso8601(precision: nil)
204
397
  ISO8601Serializer.new(self, precision: precision).serialize
205
398
  end
206
399
 
207
- delegate :<=>, to: :value
208
-
209
- protected
400
+ private
210
401
 
211
- def sum(sign, time = ::Time.current) #:nodoc:
212
- parts.inject(time) do |t,(type,number)|
402
+ def sum(sign, time = ::Time.current)
403
+ parts.inject(time) do |t, (type, number)|
213
404
  if t.acts_like?(:time) || t.acts_like?(:date)
214
405
  if type == :seconds
215
406
  t.since(sign * number)
@@ -226,10 +417,12 @@ module ActiveSupport
226
417
  end
227
418
  end
228
419
 
229
- private
230
-
231
- def method_missing(method, *args, &block) #:nodoc:
420
+ def method_missing(method, *args, &block)
232
421
  value.send(method, *args, &block)
233
422
  end
423
+
424
+ def raise_type_error(other)
425
+ raise TypeError, "no implicit conversion of #{other.class} into #{self.class}"
426
+ end
234
427
  end
235
428
  end