activesupport 4.2.11.3 → 5.0.7.2

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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +678 -348
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +2 -3
  5. data/lib/active_support/array_inquirer.rb +44 -0
  6. data/lib/active_support/backtrace_cleaner.rb +1 -1
  7. data/lib/active_support/benchmarkable.rb +1 -1
  8. data/lib/active_support/cache/file_store.rb +36 -22
  9. data/lib/active_support/cache/mem_cache_store.rb +63 -54
  10. data/lib/active_support/cache/memory_store.rb +16 -21
  11. data/lib/active_support/cache/null_store.rb +1 -4
  12. data/lib/active_support/cache/strategy/local_cache.rb +31 -20
  13. data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -4
  14. data/lib/active_support/cache.rb +71 -87
  15. data/lib/active_support/callbacks.rb +109 -113
  16. data/lib/active_support/concern.rb +1 -1
  17. data/lib/active_support/concurrency/latch.rb +11 -12
  18. data/lib/active_support/concurrency/share_lock.rb +226 -0
  19. data/lib/active_support/configurable.rb +1 -0
  20. data/lib/active_support/core_ext/array/access.rb +27 -1
  21. data/lib/active_support/core_ext/array/conversions.rb +6 -4
  22. data/lib/active_support/core_ext/array/grouping.rb +9 -18
  23. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  24. data/lib/active_support/core_ext/array/wrap.rb +5 -4
  25. data/lib/active_support/core_ext/array.rb +1 -0
  26. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
  27. data/lib/active_support/core_ext/class/attribute.rb +10 -9
  28. data/lib/active_support/core_ext/class/subclasses.rb +3 -2
  29. data/lib/active_support/core_ext/class.rb +0 -1
  30. data/lib/active_support/core_ext/date/blank.rb +12 -0
  31. data/lib/active_support/core_ext/date/calculations.rb +1 -1
  32. data/lib/active_support/core_ext/date/conversions.rb +7 -6
  33. data/lib/active_support/core_ext/date.rb +1 -1
  34. data/lib/active_support/core_ext/date_and_time/calculations.rb +100 -27
  35. data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -1
  36. data/lib/active_support/core_ext/date_and_time/zones.rb +3 -4
  37. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  38. data/lib/active_support/core_ext/date_time/calculations.rb +14 -8
  39. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  40. data/lib/active_support/core_ext/date_time.rb +1 -1
  41. data/lib/active_support/core_ext/enumerable.rb +75 -25
  42. data/lib/active_support/core_ext/file/atomic.rb +30 -25
  43. data/lib/active_support/core_ext/hash/conversions.rb +22 -2
  44. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
  45. data/lib/active_support/core_ext/hash/except.rb +9 -8
  46. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
  47. data/lib/active_support/core_ext/hash/keys.rb +25 -21
  48. data/lib/active_support/core_ext/hash/slice.rb +1 -1
  49. data/lib/active_support/core_ext/hash/transform_values.rb +11 -5
  50. data/lib/active_support/core_ext/integer/time.rb +2 -2
  51. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  52. data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
  53. data/lib/active_support/core_ext/kernel/reporting.rb +2 -84
  54. data/lib/active_support/core_ext/kernel.rb +0 -1
  55. data/lib/active_support/core_ext/load_error.rb +5 -2
  56. data/lib/active_support/core_ext/marshal.rb +7 -9
  57. data/lib/active_support/core_ext/module/aliasing.rb +6 -1
  58. data/lib/active_support/core_ext/module/anonymous.rb +10 -1
  59. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  60. data/lib/active_support/core_ext/module/attribute_accessors.rb +15 -15
  61. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  62. data/lib/active_support/core_ext/module/concerning.rb +4 -4
  63. data/lib/active_support/core_ext/module/delegation.rb +11 -20
  64. data/lib/active_support/core_ext/module/deprecation.rb +2 -2
  65. data/lib/active_support/core_ext/module/introspection.rb +8 -2
  66. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -13
  67. data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
  68. data/lib/active_support/core_ext/module/remove_method.rb +23 -0
  69. data/lib/active_support/core_ext/module.rb +1 -0
  70. data/lib/active_support/core_ext/name_error.rb +15 -2
  71. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  72. data/lib/active_support/core_ext/numeric/conversions.rb +78 -77
  73. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  74. data/lib/active_support/core_ext/numeric/time.rb +26 -6
  75. data/lib/active_support/core_ext/numeric.rb +1 -0
  76. data/lib/active_support/core_ext/object/blank.rb +15 -3
  77. data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
  78. data/lib/active_support/core_ext/object/duplicable.rb +7 -12
  79. data/lib/active_support/core_ext/object/inclusion.rb +2 -2
  80. data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
  81. data/lib/active_support/core_ext/object/json.rb +15 -7
  82. data/lib/active_support/core_ext/object/to_query.rb +1 -1
  83. data/lib/active_support/core_ext/object/try.rb +67 -21
  84. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  85. data/lib/active_support/core_ext/object.rb +0 -1
  86. data/lib/active_support/core_ext/range/conversions.rb +18 -6
  87. data/lib/active_support/core_ext/range/each.rb +16 -18
  88. data/lib/active_support/core_ext/range/include_range.rb +20 -20
  89. data/lib/active_support/core_ext/securerandom.rb +23 -0
  90. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  91. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  92. data/lib/active_support/core_ext/string/filters.rb +1 -2
  93. data/lib/active_support/core_ext/string/inflections.rb +32 -5
  94. data/lib/active_support/core_ext/string/multibyte.rb +11 -7
  95. data/lib/active_support/core_ext/string/output_safety.rb +12 -14
  96. data/lib/active_support/core_ext/string/strip.rb +3 -6
  97. data/lib/active_support/core_ext/struct.rb +3 -6
  98. data/lib/active_support/core_ext/time/calculations.rb +18 -9
  99. data/lib/active_support/core_ext/time/conversions.rb +4 -2
  100. data/lib/active_support/core_ext/time/marshal.rb +2 -29
  101. data/lib/active_support/core_ext/time/zones.rb +36 -4
  102. data/lib/active_support/core_ext/time.rb +0 -1
  103. data/lib/active_support/core_ext/uri.rb +1 -3
  104. data/lib/active_support/core_ext.rb +2 -1
  105. data/lib/active_support/dependencies/interlock.rb +55 -0
  106. data/lib/active_support/dependencies.rb +88 -95
  107. data/lib/active_support/deprecation/behaviors.rb +15 -1
  108. data/lib/active_support/deprecation/instance_delegator.rb +13 -0
  109. data/lib/active_support/deprecation/method_wrappers.rb +42 -16
  110. data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
  111. data/lib/active_support/deprecation/reporting.rb +23 -5
  112. data/lib/active_support/deprecation.rb +1 -1
  113. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  114. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  115. data/lib/active_support/duration.rb +90 -15
  116. data/lib/active_support/evented_file_update_checker.rb +199 -0
  117. data/lib/active_support/execution_wrapper.rb +126 -0
  118. data/lib/active_support/executor.rb +6 -0
  119. data/lib/active_support/file_update_checker.rb +23 -3
  120. data/lib/active_support/gem_version.rb +5 -5
  121. data/lib/active_support/gzip.rb +1 -1
  122. data/lib/active_support/hash_with_indifferent_access.rb +40 -11
  123. data/lib/active_support/i18n_railtie.rb +25 -4
  124. data/lib/active_support/inflector/inflections.rb +36 -5
  125. data/lib/active_support/inflector/methods.rb +97 -90
  126. data/lib/active_support/inflector/transliterate.rb +36 -21
  127. data/lib/active_support/json/decoding.rb +11 -10
  128. data/lib/active_support/json/encoding.rb +1 -51
  129. data/lib/active_support/key_generator.rb +7 -9
  130. data/lib/active_support/lazy_load_hooks.rb +46 -18
  131. data/lib/active_support/locale/en.yml +2 -0
  132. data/lib/active_support/log_subscriber/test_helper.rb +3 -3
  133. data/lib/active_support/log_subscriber.rb +1 -1
  134. data/lib/active_support/logger.rb +3 -4
  135. data/lib/active_support/logger_silence.rb +2 -1
  136. data/lib/active_support/logger_thread_safe_level.rb +2 -3
  137. data/lib/active_support/message_encryptor.rb +7 -7
  138. data/lib/active_support/message_verifier.rb +70 -8
  139. data/lib/active_support/multibyte/chars.rb +12 -3
  140. data/lib/active_support/multibyte/unicode.rb +44 -21
  141. data/lib/active_support/notifications/fanout.rb +5 -5
  142. data/lib/active_support/notifications/instrumenter.rb +20 -2
  143. data/lib/active_support/notifications.rb +2 -2
  144. data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -9
  145. data/lib/active_support/number_helper/number_to_delimited_converter.rb +8 -3
  146. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
  147. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -2
  148. data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
  149. data/lib/active_support/number_helper/number_to_phone_converter.rb +11 -2
  150. data/lib/active_support/number_helper/number_to_rounded_converter.rb +30 -25
  151. data/lib/active_support/number_helper.rb +90 -67
  152. data/lib/active_support/ordered_hash.rb +1 -1
  153. data/lib/active_support/ordered_options.rb +15 -1
  154. data/lib/active_support/per_thread_registry.rb +3 -0
  155. data/lib/active_support/rails.rb +2 -2
  156. data/lib/active_support/railtie.rb +6 -1
  157. data/lib/active_support/reloader.rb +129 -0
  158. data/lib/active_support/rescuable.rb +101 -47
  159. data/lib/active_support/string_inquirer.rb +1 -1
  160. data/lib/active_support/subscriber.rb +5 -10
  161. data/lib/active_support/tagged_logging.rb +8 -7
  162. data/lib/active_support/test_case.rb +17 -29
  163. data/lib/active_support/testing/assertions.rb +15 -13
  164. data/lib/active_support/testing/deprecation.rb +9 -8
  165. data/lib/active_support/testing/file_fixtures.rb +34 -0
  166. data/lib/active_support/testing/isolation.rb +22 -8
  167. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  168. data/lib/active_support/testing/stream.rb +42 -0
  169. data/lib/active_support/testing/time_helpers.rb +3 -1
  170. data/lib/active_support/time_with_zone.rb +123 -33
  171. data/lib/active_support/values/time_zone.rb +101 -47
  172. data/lib/active_support/values/unicode_tables.dat +0 -0
  173. data/lib/active_support/xml_mini/jdom.rb +1 -1
  174. data/lib/active_support/xml_mini/libxml.rb +2 -2
  175. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  176. data/lib/active_support.rb +11 -6
  177. metadata +36 -17
  178. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  179. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  180. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  181. data/lib/active_support/core_ext/object/itself.rb +0 -15
  182. data/lib/active_support/core_ext/thread.rb +0 -86
@@ -1,3 +1,5 @@
1
+ require "active_support/core_ext/time/calculations"
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  class SimpleStubs # :nodoc:
@@ -39,7 +41,7 @@ module ActiveSupport
39
41
  end
40
42
  end
41
43
 
42
- # Containing helpers that helps you test passage of time.
44
+ # Contains helpers that help you test passage of time.
43
45
  module TimeHelpers
44
46
  # Changes current time to the time in the future or in the past by a given time difference by
45
47
  # stubbing +Time.now+, +Date.today+, and +DateTime.now+.
@@ -1,3 +1,4 @@
1
+ require 'active_support/duration'
1
2
  require 'active_support/values/time_zone'
2
3
  require 'active_support/core_ext/object/acts_like'
3
4
  require 'active_support/core_ext/date_and_time/compatibility'
@@ -14,7 +15,7 @@ module ActiveSupport
14
15
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
15
16
  # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
16
17
  # Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
17
- # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
18
+ # Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
18
19
  # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
19
20
  # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
20
21
  #
@@ -41,6 +42,9 @@ module ActiveSupport
41
42
  'Time'
42
43
  end
43
44
 
45
+ PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N".freeze }
46
+ PRECISIONS[0] = '%FT%T'.freeze
47
+
44
48
  include Comparable, DateAndTime::Compatibility
45
49
  attr_reader :time_zone
46
50
 
@@ -99,7 +103,7 @@ module ActiveSupport
99
103
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
100
104
  # Time.zone.now.utc? # => false
101
105
  def utc?
102
- time_zone.name == 'UTC'
106
+ period.offset.abbreviation == :UTC || period.offset.abbreviation == :UCT
103
107
  end
104
108
  alias_method :gmt?, :utc?
105
109
 
@@ -122,22 +126,27 @@ module ActiveSupport
122
126
  utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
123
127
  end
124
128
 
125
- # Time uses +zone+ to display the time zone abbreviation, so we're
126
- # duck-typing it.
129
+ # Returns the time zone abbreviation.
130
+ #
131
+ # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
132
+ # Time.zone.now.zone # => "EST"
127
133
  def zone
128
134
  period.zone_identifier.to_s
129
135
  end
130
136
 
137
+ # Returns a string of the object's date, time, zone and offset from UTC.
138
+ #
139
+ # Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
131
140
  def inspect
132
141
  "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
133
142
  end
134
143
 
144
+ # Returns a string of the object's date and time in the ISO 8601 standard
145
+ # format.
146
+ #
147
+ # Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00"
135
148
  def xmlschema(fraction_digits = 0)
136
- fraction = if fraction_digits.to_i > 0
137
- (".%06i" % time.usec)[0, fraction_digits.to_i + 1]
138
- end
139
-
140
- "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}#{formatted_offset(true, 'Z')}"
149
+ "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'.freeze)}"
141
150
  end
142
151
  alias_method :iso8601, :xmlschema
143
152
 
@@ -166,11 +175,8 @@ module ActiveSupport
166
175
  end
167
176
 
168
177
  def encode_with(coder) #:nodoc:
169
- if coder.respond_to?(:represent_object)
170
- coder.represent_object(nil, utc)
171
- else
172
- coder.represent_scalar(nil, utc.strftime("%Y-%m-%d %H:%M:%S.%9NZ"))
173
- end
178
+ coder.tag = '!ruby/object:ActiveSupport::TimeWithZone'
179
+ coder.map = { 'utc' => utc, 'zone' => time_zone, 'time' => time }
174
180
  end
175
181
 
176
182
  # Returns a string of the object's date and time in the format used by
@@ -192,7 +198,7 @@ module ActiveSupport
192
198
 
193
199
  # Returns a string of the object's date and time.
194
200
  # Accepts an optional <tt>format</tt>:
195
- # * <tt>:default</tt> - default value, mimics Ruby 1.9 Time#to_s format.
201
+ # * <tt>:default</tt> - default value, mimics Ruby Time#to_s format.
196
202
  # * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_formatted_s(:db).
197
203
  # * Any key in <tt>Time::DATE_FORMATS</tt> can be used. See active_support/core_ext/time/conversions.rb.
198
204
  def to_s(format = :default)
@@ -201,7 +207,7 @@ module ActiveSupport
201
207
  elsif formatter = ::Time::DATE_FORMATS[format]
202
208
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
203
209
  else
204
- "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby 1.9 Time#to_s format
210
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
205
211
  end
206
212
  end
207
213
  alias_method :to_formatted_s, :to_s
@@ -240,6 +246,7 @@ module ActiveSupport
240
246
  utc.future?
241
247
  end
242
248
 
249
+ # Returns +true+ if +other+ is equal to current object.
243
250
  def eql?(other)
244
251
  other.eql?(utc)
245
252
  end
@@ -248,9 +255,23 @@ module ActiveSupport
248
255
  utc.hash
249
256
  end
250
257
 
258
+ # Adds an interval of time to the current object's time and returns that
259
+ # value as a new TimeWithZone object.
260
+ #
261
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
262
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
263
+ # now + 1000 # => Sun, 02 Nov 2014 01:43:08 EDT -04:00
264
+ #
265
+ # If we're adding a Duration of variable length (i.e., years, months, days),
266
+ # move forward from #time, otherwise move forward from #utc, for accuracy
267
+ # when moving across DST boundaries.
268
+ #
269
+ # For instance, a time + 24.hours will advance exactly 24 hours, while a
270
+ # time + 1.day will advance 23-25 hours, depending on the day.
271
+ #
272
+ # now + 24.hours # => Mon, 03 Nov 2014 00:26:28 EST -05:00
273
+ # now + 1.day # => Mon, 03 Nov 2014 01:26:28 EST -05:00
251
274
  def +(other)
252
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
253
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
254
275
  if duration_of_variable_length?(other)
255
276
  method_missing(:+, other)
256
277
  else
@@ -258,10 +279,26 @@ module ActiveSupport
258
279
  result.in_time_zone(time_zone)
259
280
  end
260
281
  end
282
+ alias_method :since, :+
283
+ alias_method :in, :+
261
284
 
285
+ # Returns a new TimeWithZone object that represents the difference between
286
+ # the current object's time and the +other+ time.
287
+ #
288
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
289
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
290
+ # now - 1000 # => Mon, 03 Nov 2014 00:09:48 EST -05:00
291
+ #
292
+ # If subtracting a Duration of variable length (i.e., years, months, days),
293
+ # move backward from #time, otherwise move backward from #utc, for accuracy
294
+ # when moving across DST boundaries.
295
+ #
296
+ # For instance, a time - 24.hours will go subtract exactly 24 hours, while a
297
+ # time - 1.day will subtract 23-25 hours, depending on the day.
298
+ #
299
+ # now - 24.hours # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
300
+ # now - 1.day # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
262
301
  def -(other)
263
- # If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time,
264
- # otherwise move backwards #utc, for accuracy when moving across DST boundaries
265
302
  if other.acts_like?(:time)
266
303
  to_time - other.to_time
267
304
  elsif duration_of_variable_length?(other)
@@ -272,21 +309,48 @@ module ActiveSupport
272
309
  end
273
310
  end
274
311
 
275
- def since(other)
276
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
277
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
278
- if duration_of_variable_length?(other)
279
- method_missing(:since, other)
280
- else
281
- utc.since(other).in_time_zone(time_zone)
282
- end
283
- end
284
- alias_method :in, :since
285
-
312
+ # Subtracts an interval of time from the current object's time and returns
313
+ # the result as a new TimeWithZone object.
314
+ #
315
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
316
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
317
+ # now.ago(1000) # => Mon, 03 Nov 2014 00:09:48 EST -05:00
318
+ #
319
+ # If we're subtracting a Duration of variable length (i.e., years, months,
320
+ # days), move backward from #time, otherwise move backward from #utc, for
321
+ # accuracy when moving across DST boundaries.
322
+ #
323
+ # For instance, <tt>time.ago(24.hours)</tt> will move back exactly 24 hours,
324
+ # while <tt>time.ago(1.day)</tt> will move back 23-25 hours, depending on
325
+ # the day.
326
+ #
327
+ # now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
328
+ # now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
286
329
  def ago(other)
287
330
  since(-other)
288
331
  end
289
332
 
333
+ # Uses Date to provide precise Time calculations for years, months, and days
334
+ # according to the proleptic Gregorian calendar. The result is returned as a
335
+ # new TimeWithZone object.
336
+ #
337
+ # The +options+ parameter takes a hash with any of these keys:
338
+ # <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>,
339
+ # <tt>:hours</tt>, <tt>:minutes</tt>, <tt>:seconds</tt>.
340
+ #
341
+ # If advancing by a value of variable length (i.e., years, weeks, months,
342
+ # days), move forward from #time, otherwise move forward from #utc, for
343
+ # accuracy when moving across DST boundaries.
344
+ #
345
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
346
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
347
+ # now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29 EDT -04:00
348
+ # now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28 EDT -04:00
349
+ # now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28 EST -05:00
350
+ # now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28 EST -05:00
351
+ # now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28 EST -05:00
352
+ # now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28 EST -05:00
353
+ # now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28 EST -05:00
290
354
  def advance(options)
291
355
  # If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
292
356
  # otherwise advance from #utc, for accuracy when moving across DST boundaries
@@ -305,25 +369,46 @@ module ActiveSupport
305
369
  EOV
306
370
  end
307
371
 
372
+ # Returns Array of parts of Time in sequence of
373
+ # [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].
374
+ #
375
+ # now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00
376
+ # now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
308
377
  def to_a
309
378
  [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
310
379
  end
311
380
 
381
+ # Returns the object's date and time as a floating point number of seconds
382
+ # since the Epoch (January 1, 1970 00:00 UTC).
383
+ #
384
+ # Time.zone.now.to_f # => 1417709320.285418
312
385
  def to_f
313
386
  utc.to_f
314
387
  end
315
388
 
389
+ # Returns the object's date and time as an integer number of seconds
390
+ # since the Epoch (January 1, 1970 00:00 UTC).
391
+ #
392
+ # Time.zone.now.to_i # => 1417709320
316
393
  def to_i
317
394
  utc.to_i
318
395
  end
319
396
  alias_method :tv_sec, :to_i
320
397
 
398
+ # Returns the object's date and time as a rational number of seconds
399
+ # since the Epoch (January 1, 1970 00:00 UTC).
400
+ #
401
+ # Time.zone.now.to_r # => (708854548642709/500000)
321
402
  def to_r
322
403
  utc.to_r
323
404
  end
324
405
 
406
+ # Returns an instance of DateTime with the timezone's UTC offset
407
+ #
408
+ # Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
409
+ # Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
325
410
  def to_datetime
326
- @to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
411
+ utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
327
412
  end
328
413
 
329
414
  # Returns an instance of +Time+, either with the same UTC offset
@@ -348,6 +433,11 @@ module ActiveSupport
348
433
  end
349
434
  alias_method :kind_of?, :is_a?
350
435
 
436
+ # An instance of ActiveSupport::TimeWithZone is never blank
437
+ def blank?
438
+ false
439
+ end
440
+
351
441
  def freeze
352
442
  # preload instance variables before freezing
353
443
  period; utc; time; to_datetime; to_time
@@ -404,7 +494,7 @@ module ActiveSupport
404
494
  end
405
495
 
406
496
  def duration_of_variable_length?(obj)
407
- ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include?(p[0]) }
497
+ ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :weeks, :days].include?(p[0]) }
408
498
  end
409
499
 
410
500
  def wrap_with_time_zone(time)
@@ -1,7 +1,6 @@
1
1
  require 'tzinfo'
2
- require 'thread_safe'
2
+ require 'concurrent/map'
3
3
  require 'active_support/core_ext/object/blank'
4
- require 'active_support/core_ext/object/try'
5
4
 
6
5
  module ActiveSupport
7
6
  # The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
@@ -23,15 +22,9 @@ module ActiveSupport
23
22
  # config.time_zone = 'Eastern Time (US & Canada)'
24
23
  # end
25
24
  #
26
- # Time.zone # => #<TimeZone:0x514834...>
25
+ # Time.zone # => #<ActiveSupport::TimeZone:0x514834...>
27
26
  # Time.zone.name # => "Eastern Time (US & Canada)"
28
27
  # Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00
29
- #
30
- # The version of TZInfo bundled with Active Support only includes the
31
- # definitions necessary to support the zones defined by the TimeZone class.
32
- # If you need to use zones that aren't defined by TimeZone, you'll need to
33
- # install the TZInfo gem (if a recent version of the gem is installed locally,
34
- # this will be used instead of the bundled version.)
35
28
  class TimeZone
36
29
  # Keys are Rails TimeZone names, values are TZInfo identifiers.
37
30
  MAPPING = {
@@ -92,7 +85,8 @@ module ActiveSupport
92
85
  "Paris" => "Europe/Paris",
93
86
  "Amsterdam" => "Europe/Amsterdam",
94
87
  "Berlin" => "Europe/Berlin",
95
- "Bern" => "Europe/Berlin",
88
+ "Bern" => "Europe/Zurich",
89
+ "Zurich" => "Europe/Zurich",
96
90
  "Rome" => "Europe/Rome",
97
91
  "Stockholm" => "Europe/Stockholm",
98
92
  "Vienna" => "Europe/Vienna",
@@ -189,13 +183,14 @@ module ActiveSupport
189
183
  UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
190
184
  UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(':', '')
191
185
 
192
- @lazy_zones_map = ThreadSafe::Cache.new
186
+ @lazy_zones_map = Concurrent::Map.new
187
+ @country_zones = Concurrent::Map.new
193
188
 
194
189
  class << self
195
190
  # Assumes self represents an offset from UTC in seconds (as returned from
196
191
  # Time#utc_offset) and turns this into an +HH:MM formatted string.
197
192
  #
198
- # TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
193
+ # ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
199
194
  def seconds_to_utc_offset(seconds, colon = true)
200
195
  format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
201
196
  sign = (seconds < 0 ? '-' : '+')
@@ -205,7 +200,7 @@ module ActiveSupport
205
200
  end
206
201
 
207
202
  def find_tzinfo(name)
208
- TZInfo::TimezoneProxy.new(MAPPING[name] || name)
203
+ TZInfo::Timezone.new(MAPPING[name] || name)
209
204
  end
210
205
 
211
206
  alias_method :create, :new
@@ -224,13 +219,6 @@ module ActiveSupport
224
219
  @zones ||= zones_map.values.sort
225
220
  end
226
221
 
227
- def zones_map #:nodoc:
228
- @zones_map ||= begin
229
- MAPPING.each_key {|place| self[place]} # load all the zones
230
- @lazy_zones_map
231
- end
232
- end
233
-
234
222
  # Locate a specific time zone object. If the argument is a string, it
235
223
  # is interpreted to mean the name of the timezone to locate. If it is a
236
224
  # numeric value it is either the hour offset, or the second offset, of the
@@ -240,7 +228,7 @@ module ActiveSupport
240
228
  case arg
241
229
  when String
242
230
  begin
243
- @lazy_zones_map[arg] ||= create(arg).tap { |tz| tz.utc_offset }
231
+ @lazy_zones_map[arg] ||= create(arg)
244
232
  rescue TZInfo::InvalidTimezoneIdentifier
245
233
  nil
246
234
  end
@@ -255,8 +243,37 @@ module ActiveSupport
255
243
  # A convenience method for returning a collection of TimeZone objects
256
244
  # for time zones in the USA.
257
245
  def us_zones
258
- @us_zones ||= all.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ }
246
+ country_zones(:us)
259
247
  end
248
+
249
+ # A convenience method for returning a collection of TimeZone objects
250
+ # for time zones in the country specified by its ISO 3166-1 Alpha2 code.
251
+ def country_zones(country_code)
252
+ code = country_code.to_s.upcase
253
+ @country_zones[code] ||= load_country_zones(code)
254
+ end
255
+
256
+ private
257
+ def load_country_zones(code)
258
+ country = TZInfo::Country.get(code)
259
+ country.zone_identifiers.map do |tz_id|
260
+ if MAPPING.value?(tz_id)
261
+ MAPPING.inject([]) do |memo, (key, value)|
262
+ memo << self[key] if value == tz_id
263
+ memo
264
+ end
265
+ else
266
+ create(tz_id, nil, TZInfo::Timezone.new(tz_id))
267
+ end
268
+ end.flatten(1).sort!
269
+ end
270
+
271
+ def zones_map
272
+ @zones_map ||= begin
273
+ MAPPING.each_key {|place| self[place]} # load all the zones
274
+ @lazy_zones_map
275
+ end
276
+ end
260
277
  end
261
278
 
262
279
  include Comparable
@@ -273,10 +290,6 @@ module ActiveSupport
273
290
  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
274
291
  end
275
292
 
276
- def init_with(coder) #:nodoc:
277
- initialize(coder['name'])
278
- end
279
-
280
293
  # Returns the offset of this time zone from UTC in seconds.
281
294
  def utc_offset
282
295
  if @utc_offset
@@ -286,8 +299,12 @@ module ActiveSupport
286
299
  end
287
300
  end
288
301
 
289
- # Returns the offset of this time zone as a formatted string, of the
290
- # format "+HH:MM".
302
+ # Returns a formatted string of the offset from UTC, or an alternative
303
+ # string if the time zone is already UTC.
304
+ #
305
+ # zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
306
+ # zone.formatted_offset # => "-06:00"
307
+ # zone.formatted_offset(false) # => "-0600"
291
308
  def formatted_offset(colon=true, alternate_utc_string = nil)
292
309
  utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
293
310
  end
@@ -349,24 +366,31 @@ module ActiveSupport
349
366
  #
350
367
  # Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
351
368
  def parse(str, now=now())
352
- parts = Date._parse(str, false)
353
- return if parts.empty?
354
-
355
- time = Time.new(
356
- parts.fetch(:year, now.year),
357
- parts.fetch(:mon, now.month),
358
- parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
359
- parts.fetch(:hour, 0),
360
- parts.fetch(:min, 0),
361
- parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
362
- parts.fetch(:offset, 0)
363
- )
364
-
365
- if parts[:offset]
366
- TimeWithZone.new(time.utc, self)
367
- else
368
- TimeWithZone.new(nil, self, time)
369
- end
369
+ parts_to_time(Date._parse(str, false), now)
370
+ end
371
+
372
+ # Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
373
+ #
374
+ # Assumes that +str+ is a time in the time zone +self+,
375
+ # unless +format+ includes an explicit time zone.
376
+ # (This is the same behavior as +parse+.)
377
+ # In either case, the returned TimeWithZone has the timezone of +self+.
378
+ #
379
+ # Time.zone = 'Hawaii' # => "Hawaii"
380
+ # Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
381
+ #
382
+ # If upper components are missing from the string, they are supplied from
383
+ # TimeZone#now:
384
+ #
385
+ # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
386
+ # Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
387
+ #
388
+ # However, if the date component is not provided, but any other upper
389
+ # components are supplied, then the day of the month defaults to 1:
390
+ #
391
+ # Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
392
+ def strptime(str, format, now=now())
393
+ parts_to_time(DateTime._strptime(str, format), now)
370
394
  end
371
395
 
372
396
  # Returns an ActiveSupport::TimeWithZone instance representing the current
@@ -378,7 +402,7 @@ module ActiveSupport
378
402
  time_now.utc.in_time_zone(self)
379
403
  end
380
404
 
381
- # Return the current date in this time zone.
405
+ # Returns the current date in this time zone.
382
406
  def today
383
407
  tzinfo.now.to_date
384
408
  end
@@ -422,7 +446,37 @@ module ActiveSupport
422
446
  tzinfo.periods_for_local(time)
423
447
  end
424
448
 
449
+ def init_with(coder) #:nodoc:
450
+ initialize(coder['name'])
451
+ end
452
+
453
+ def encode_with(coder) #:nodoc:
454
+ coder.tag ="!ruby/object:#{self.class}"
455
+ coder.map = { 'name' => tzinfo.name }
456
+ end
457
+
425
458
  private
459
+ def parts_to_time(parts, now)
460
+ raise ArgumentError, "invalid date" if parts.nil?
461
+ return if parts.empty?
462
+
463
+ time = Time.new(
464
+ parts.fetch(:year, now.year),
465
+ parts.fetch(:mon, now.month),
466
+ parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
467
+ parts.fetch(:hour, 0),
468
+ parts.fetch(:min, 0),
469
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
470
+ parts.fetch(:offset, 0)
471
+ )
472
+
473
+ if parts[:offset]
474
+ TimeWithZone.new(time.utc, self)
475
+ else
476
+ TimeWithZone.new(nil, self, time)
477
+ end
478
+ end
479
+
426
480
  def time_now
427
481
  Time.now
428
482
  end
@@ -142,7 +142,7 @@ module ActiveSupport
142
142
  (0...attributes.length).each do |i|
143
143
  attribute_hash[CONTENT_KEY] ||= ''
144
144
  attribute_hash[attributes.item(i).name] = attributes.item(i).value
145
- end
145
+ end
146
146
  attribute_hash
147
147
  end
148
148
 
@@ -73,5 +73,5 @@ module LibXML #:nodoc:
73
73
  end
74
74
  end
75
75
 
76
- LibXML::XML::Document.send(:include, LibXML::Conversions::Document)
77
- LibXML::XML::Node.send(:include, LibXML::Conversions::Node)
76
+ LibXML::XML::Document.include(LibXML::Conversions::Document)
77
+ LibXML::XML::Node.include(LibXML::Conversions::Node)
@@ -75,7 +75,7 @@ module ActiveSupport
75
75
  end
76
76
  end
77
77
 
78
- Nokogiri::XML::Document.send(:include, Conversions::Document)
79
- Nokogiri::XML::Node.send(:include, Conversions::Node)
78
+ Nokogiri::XML::Document.include(Conversions::Document)
79
+ Nokogiri::XML::Node.include(Conversions::Node)
80
80
  end
81
81
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2014 David Heinemeier Hansson
2
+ # Copyright (c) 2005-2016 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -34,9 +34,13 @@ module ActiveSupport
34
34
  autoload :Concern
35
35
  autoload :Dependencies
36
36
  autoload :DescendantsTracker
37
+ autoload :ExecutionWrapper
38
+ autoload :Executor
37
39
  autoload :FileUpdateChecker
40
+ autoload :EventedFileUpdateChecker
38
41
  autoload :LogSubscriber
39
42
  autoload :Notifications
43
+ autoload :Reloader
40
44
 
41
45
  eager_autoload do
42
46
  autoload :BacktraceCleaner
@@ -60,6 +64,7 @@ module ActiveSupport
60
64
  autoload :StringInquirer
61
65
  autoload :TaggedLogging
62
66
  autoload :XmlMini
67
+ autoload :ArrayInquirer
63
68
  end
64
69
 
65
70
  autoload :Rescuable
@@ -72,14 +77,14 @@ module ActiveSupport
72
77
  NumberHelper.eager_load!
73
78
  end
74
79
 
75
- @@test_order = nil
80
+ cattr_accessor :test_order # :nodoc:
76
81
 
77
- def self.test_order=(new_order) # :nodoc:
78
- @@test_order = new_order
82
+ def self.halt_callback_chains_on_return_false
83
+ Callbacks.halt_and_display_warning_on_return_false
79
84
  end
80
85
 
81
- def self.test_order # :nodoc:
82
- @@test_order
86
+ def self.halt_callback_chains_on_return_false=(value)
87
+ Callbacks.halt_and_display_warning_on_return_false = value
83
88
  end
84
89
 
85
90
  def self.to_time_preserves_timezone