activesupport 4.0.13 → 4.2.11.3

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 (166) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +406 -418
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -2
  5. data/lib/active_support/backtrace_cleaner.rb +8 -8
  6. data/lib/active_support/benchmarkable.rb +0 -10
  7. data/lib/active_support/cache/file_store.rb +32 -22
  8. data/lib/active_support/cache/mem_cache_store.rb +5 -7
  9. data/lib/active_support/cache/memory_store.rb +1 -0
  10. data/lib/active_support/cache/strategy/local_cache.rb +11 -30
  11. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  12. data/lib/active_support/cache.rb +75 -41
  13. data/lib/active_support/callbacks.rb +482 -261
  14. data/lib/active_support/concern.rb +23 -7
  15. data/lib/active_support/configurable.rb +1 -1
  16. data/lib/active_support/core_ext/array/access.rb +11 -1
  17. data/lib/active_support/core_ext/array/conversions.rb +2 -17
  18. data/lib/active_support/core_ext/array/grouping.rb +29 -12
  19. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
  20. data/lib/active_support/core_ext/array.rb +0 -1
  21. data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -15
  22. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +16 -0
  23. data/lib/active_support/core_ext/class/attribute.rb +1 -2
  24. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -170
  25. data/lib/active_support/core_ext/class/delegating_attributes.rb +13 -8
  26. data/lib/active_support/core_ext/class/subclasses.rb +0 -2
  27. data/lib/active_support/core_ext/class.rb +0 -1
  28. data/lib/active_support/core_ext/date/calculations.rb +10 -0
  29. data/lib/active_support/core_ext/date/conversions.rb +9 -1
  30. data/lib/active_support/core_ext/date/zones.rb +2 -33
  31. data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -11
  32. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  33. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  34. data/lib/active_support/core_ext/date_time/calculations.rb +45 -22
  35. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  36. data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
  37. data/lib/active_support/core_ext/date_time/zones.rb +3 -21
  38. data/lib/active_support/core_ext/date_time.rb +1 -0
  39. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  40. data/lib/active_support/core_ext/enumerable.rb +17 -1
  41. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  42. data/lib/active_support/core_ext/hash/compact.rb +24 -0
  43. data/lib/active_support/core_ext/hash/conversions.rb +9 -8
  44. data/lib/active_support/core_ext/hash/except.rb +8 -2
  45. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
  46. data/lib/active_support/core_ext/hash/keys.rb +25 -19
  47. data/lib/active_support/core_ext/hash/slice.rb +8 -2
  48. data/lib/active_support/core_ext/hash/transform_values.rb +23 -0
  49. data/lib/active_support/core_ext/hash.rb +2 -1
  50. data/lib/active_support/core_ext/integer/time.rb +0 -15
  51. data/lib/active_support/core_ext/kernel/concern.rb +10 -0
  52. data/lib/active_support/core_ext/kernel/debugger.rb +1 -1
  53. data/lib/active_support/core_ext/kernel/reporting.rb +13 -2
  54. data/lib/active_support/core_ext/kernel.rb +3 -2
  55. data/lib/active_support/core_ext/load_error.rb +4 -1
  56. data/lib/active_support/core_ext/marshal.rb +8 -5
  57. data/lib/active_support/core_ext/module/aliasing.rb +2 -2
  58. data/lib/active_support/core_ext/module/attr_internal.rb +2 -1
  59. data/lib/active_support/core_ext/module/attribute_accessors.rb +160 -14
  60. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  61. data/lib/active_support/core_ext/module/delegation.rb +53 -25
  62. data/lib/active_support/core_ext/module/deprecation.rb +0 -2
  63. data/lib/active_support/core_ext/module/introspection.rb +0 -16
  64. data/lib/active_support/core_ext/module/method_transplanting.rb +13 -0
  65. data/lib/active_support/core_ext/module.rb +1 -0
  66. data/lib/active_support/core_ext/numeric/conversions.rb +11 -3
  67. data/lib/active_support/core_ext/numeric/time.rb +4 -29
  68. data/lib/active_support/core_ext/object/blank.rb +44 -18
  69. data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
  70. data/lib/active_support/core_ext/object/duplicable.rb +72 -33
  71. data/lib/active_support/core_ext/object/inclusion.rb +16 -15
  72. data/lib/active_support/core_ext/object/itself.rb +15 -0
  73. data/lib/active_support/core_ext/object/json.rb +197 -0
  74. data/lib/active_support/core_ext/object/to_query.rb +14 -6
  75. data/lib/active_support/core_ext/object/try.rb +36 -14
  76. data/lib/active_support/core_ext/object/with_options.rb +30 -3
  77. data/lib/active_support/core_ext/object.rb +2 -1
  78. data/lib/active_support/core_ext/string/access.rb +35 -35
  79. data/lib/active_support/core_ext/string/conversions.rb +10 -9
  80. data/lib/active_support/core_ext/string/exclude.rb +3 -3
  81. data/lib/active_support/core_ext/string/filters.rb +51 -3
  82. data/lib/active_support/core_ext/string/inflections.rb +15 -10
  83. data/lib/active_support/core_ext/string/output_safety.rb +97 -33
  84. data/lib/active_support/core_ext/string/zones.rb +1 -0
  85. data/lib/active_support/core_ext/thread.rb +12 -5
  86. data/lib/active_support/core_ext/time/calculations.rb +47 -68
  87. data/lib/active_support/core_ext/time/compatibility.rb +14 -0
  88. data/lib/active_support/core_ext/time/conversions.rb +4 -2
  89. data/lib/active_support/core_ext/time/zones.rb +2 -20
  90. data/lib/active_support/core_ext/time.rb +1 -0
  91. data/lib/active_support/core_ext.rb +0 -1
  92. data/lib/active_support/dependencies/autoload.rb +1 -1
  93. data/lib/active_support/dependencies.rb +64 -25
  94. data/lib/active_support/deprecation/behaviors.rb +4 -4
  95. data/lib/active_support/deprecation.rb +4 -4
  96. data/lib/active_support/duration.rb +55 -11
  97. data/lib/active_support/file_update_checker.rb +1 -1
  98. data/lib/active_support/gem_version.rb +15 -0
  99. data/lib/active_support/hash_with_indifferent_access.rb +39 -11
  100. data/lib/active_support/i18n.rb +4 -4
  101. data/lib/active_support/i18n_railtie.rb +1 -7
  102. data/lib/active_support/inflections.rb +6 -1
  103. data/lib/active_support/inflector/inflections.rb +19 -19
  104. data/lib/active_support/inflector/methods.rb +66 -25
  105. data/lib/active_support/json/decoding.rb +15 -22
  106. data/lib/active_support/json/encoding.rb +125 -286
  107. data/lib/active_support/key_generator.rb +8 -10
  108. data/lib/active_support/lazy_load_hooks.rb +1 -1
  109. data/lib/active_support/log_subscriber/test_helper.rb +1 -1
  110. data/lib/active_support/logger.rb +51 -1
  111. data/lib/active_support/logger_silence.rb +7 -4
  112. data/lib/active_support/logger_thread_safe_level.rb +32 -0
  113. data/lib/active_support/message_encryptor.rb +14 -6
  114. data/lib/active_support/message_verifier.rb +16 -12
  115. data/lib/active_support/multibyte/chars.rb +2 -3
  116. data/lib/active_support/multibyte/unicode.rb +46 -58
  117. data/lib/active_support/notifications/fanout.rb +12 -7
  118. data/lib/active_support/notifications/instrumenter.rb +2 -1
  119. data/lib/active_support/notifications.rb +11 -6
  120. data/lib/active_support/number_helper/number_converter.rb +182 -0
  121. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  122. data/lib/active_support/number_helper/number_to_delimited_converter.rb +23 -0
  123. data/lib/active_support/number_helper/number_to_human_converter.rb +66 -0
  124. data/lib/active_support/number_helper/number_to_human_size_converter.rb +58 -0
  125. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  126. data/lib/active_support/number_helper/number_to_phone_converter.rb +49 -0
  127. data/lib/active_support/number_helper/number_to_rounded_converter.rb +87 -0
  128. data/lib/active_support/number_helper.rb +32 -324
  129. data/lib/active_support/ordered_options.rb +8 -0
  130. data/lib/active_support/per_thread_registry.rb +13 -10
  131. data/lib/active_support/security_utils.rb +27 -0
  132. data/lib/active_support/subscriber.rb +35 -3
  133. data/lib/active_support/test_case.rb +52 -19
  134. data/lib/active_support/testing/assertions.rb +1 -31
  135. data/lib/active_support/testing/autorun.rb +2 -2
  136. data/lib/active_support/testing/constant_lookup.rb +1 -5
  137. data/lib/active_support/testing/declarative.rb +7 -21
  138. data/lib/active_support/testing/isolation.rb +29 -69
  139. data/lib/active_support/testing/setup_and_teardown.rb +17 -2
  140. data/lib/active_support/testing/tagged_logging.rb +2 -2
  141. data/lib/active_support/testing/time_helpers.rb +134 -0
  142. data/lib/active_support/time.rb +0 -2
  143. data/lib/active_support/time_with_zone.rb +60 -40
  144. data/lib/active_support/values/time_zone.rb +101 -101
  145. data/lib/active_support/values/unicode_tables.dat +0 -0
  146. data/lib/active_support/version.rb +4 -7
  147. data/lib/active_support/xml_mini/jdom.rb +6 -5
  148. data/lib/active_support/xml_mini/libxml.rb +1 -3
  149. data/lib/active_support/xml_mini/libxmlsax.rb +1 -4
  150. data/lib/active_support/xml_mini/nokogiri.rb +1 -3
  151. data/lib/active_support/xml_mini/nokogirisax.rb +1 -3
  152. data/lib/active_support/xml_mini/rexml.rb +7 -8
  153. data/lib/active_support/xml_mini.rb +33 -15
  154. data/lib/active_support.rb +27 -2
  155. metadata +43 -43
  156. data/lib/active_support/basic_object.rb +0 -11
  157. data/lib/active_support/buffered_logger.rb +0 -21
  158. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  159. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  160. data/lib/active_support/core_ext/logger.rb +0 -67
  161. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  162. data/lib/active_support/core_ext/proc.rb +0 -17
  163. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  164. data/lib/active_support/file_watcher.rb +0 -36
  165. data/lib/active_support/json/variable.rb +0 -18
  166. data/lib/active_support/testing/pending.rb +0 -14
@@ -78,7 +78,7 @@ module DateAndTime
78
78
  # Returns a new date/time at the start of the month.
79
79
  # DateTime objects will have a time set to 0:00.
80
80
  def beginning_of_month
81
- first_hour{ change(:day => 1) }
81
+ first_hour(change(:day => 1))
82
82
  end
83
83
  alias :at_beginning_of_month :beginning_of_month
84
84
 
@@ -109,11 +109,22 @@ module DateAndTime
109
109
  alias :at_beginning_of_year :beginning_of_year
110
110
 
111
111
  # Returns a new date/time representing the given day in the next week.
112
+ #
113
+ # today = Date.today # => Thu, 07 May 2015
114
+ # today.next_week # => Mon, 11 May 2015
115
+ #
112
116
  # The +given_day_in_next_week+ defaults to the beginning of the week
113
117
  # which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
118
+ #
119
+ # today = Date.today # => Thu, 07 May 2015
120
+ # today.next_week(:friday) # => Fri, 15 May 2015
121
+ #
114
122
  # when set. +DateTime+ objects have their time set to 0:00.
123
+ #
124
+ # now = Time.current # => Thu, 07 May 2015 13:31:16 UTC +00:00
125
+ # now.next_week # => Mon, 11 May 2015 00:00:00 UTC +00:00
115
126
  def next_week(given_day_in_next_week = Date.beginning_of_week)
116
- first_hour{ weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)) }
127
+ first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
117
128
  end
118
129
 
119
130
  # Short-hand for months_since(1).
@@ -136,7 +147,7 @@ module DateAndTime
136
147
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
137
148
  # DateTime objects have their time set to 0:00.
138
149
  def prev_week(start_day = Date.beginning_of_week)
139
- first_hour{ weeks_ago(1).beginning_of_week.days_since(days_span(start_day)) }
150
+ first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
140
151
  end
141
152
  alias_method :last_week, :prev_week
142
153
 
@@ -188,7 +199,7 @@ module DateAndTime
188
199
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
189
200
  # DateTime objects have their time set to 23:59:59.
190
201
  def end_of_week(start_day = Date.beginning_of_week)
191
- last_hour{ days_since(6 - days_to_week_start(start_day)) }
202
+ last_hour(days_since(6 - days_to_week_start(start_day)))
192
203
  end
193
204
  alias :at_end_of_week :end_of_week
194
205
 
@@ -202,7 +213,7 @@ module DateAndTime
202
213
  # DateTime objects will have a time set to 23:59:59.
203
214
  def end_of_month
204
215
  last_day = ::Time.days_in_month(month, year)
205
- last_hour{ days_since(last_day - day) }
216
+ last_hour(days_since(last_day - day))
206
217
  end
207
218
  alias :at_end_of_month :end_of_month
208
219
 
@@ -213,16 +224,35 @@ module DateAndTime
213
224
  end
214
225
  alias :at_end_of_year :end_of_year
215
226
 
227
+ # Returns a Range representing the whole week of the current date/time.
228
+ # Week starts on start_day, default is <tt>Date.week_start</tt> or <tt>config.week_start</tt> when set.
229
+ def all_week(start_day = Date.beginning_of_week)
230
+ beginning_of_week(start_day)..end_of_week(start_day)
231
+ end
232
+
233
+ # Returns a Range representing the whole month of the current date/time.
234
+ def all_month
235
+ beginning_of_month..end_of_month
236
+ end
237
+
238
+ # Returns a Range representing the whole quarter of the current date/time.
239
+ def all_quarter
240
+ beginning_of_quarter..end_of_quarter
241
+ end
242
+
243
+ # Returns a Range representing the whole year of the current date/time.
244
+ def all_year
245
+ beginning_of_year..end_of_year
246
+ end
247
+
216
248
  private
217
249
 
218
- def first_hour
219
- result = yield
220
- acts_like?(:time) ? result.change(:hour => 0) : result
250
+ def first_hour(date_or_time)
251
+ date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
221
252
  end
222
253
 
223
- def last_hour
224
- result = yield
225
- acts_like?(:time) ? result.end_of_day : result
254
+ def last_hour(date_or_time)
255
+ date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
226
256
  end
227
257
 
228
258
  def days_span(day)
@@ -0,0 +1,15 @@
1
+ require 'active_support/core_ext/module/attribute_accessors'
2
+ require 'active_support/core_ext/module/remove_method'
3
+
4
+ module DateAndTime
5
+ module Compatibility
6
+ # If true, +to_time+ preserves the timezone offset of receiver.
7
+ #
8
+ # NOTE: With Ruby 2.4+ the default for +to_time+ changed from
9
+ # converting to the local system time, to preserving the offset
10
+ # of the receiver. For backwards compatibility we're overriding
11
+ # this behavior, but new apps will have an initializer that sets
12
+ # this to true, because the new behavior is preferred.
13
+ mattr_accessor(:preserve_timezone, instance_writer: false) { false }
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ module DateAndTime
2
+ module Zones
3
+ # Returns the simultaneous time in <tt>Time.zone</tt> if a zone is given or
4
+ # if Time.zone_default is set. Otherwise, it returns the current time.
5
+ #
6
+ # Time.zone = 'Hawaii' # => 'Hawaii'
7
+ # DateTime.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
8
+ # Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00
9
+ #
10
+ # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
11
+ # instead of the operating system's time zone.
12
+ #
13
+ # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
14
+ # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
15
+ #
16
+ # Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
17
+ # DateTime.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
18
+ # Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
19
+ def in_time_zone(zone = ::Time.zone)
20
+ time_zone = ::Time.find_zone! zone
21
+ time = acts_like?(:time) ? self : nil
22
+
23
+ if time_zone
24
+ time_with_zone(time, time_zone)
25
+ else
26
+ time || self.to_time
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def time_with_zone(time, zone)
33
+ if time
34
+ ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
35
+ else
36
+ ActiveSupport::TimeWithZone.new(nil, zone, to_time(:utc))
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -1,14 +1,7 @@
1
- require 'active_support/deprecation'
1
+ require 'date'
2
2
 
3
3
  class DateTime
4
4
  class << self
5
- # *DEPRECATED*: Use +DateTime.civil_from_format+ directly.
6
- def local_offset
7
- ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. Use DateTime.civil_from_format directly.'
8
-
9
- ::Time.local(2012).utc_offset.to_r / 86400
10
- end
11
-
12
5
  # Returns <tt>Time.zone.now.to_datetime</tt> when <tt>Time.zone</tt> or
13
6
  # <tt>config.time_zone</tt> are set, otherwise returns
14
7
  # <tt>Time.now.to_datetime</tt>.
@@ -17,16 +10,6 @@ class DateTime
17
10
  end
18
11
  end
19
12
 
20
- # Tells whether the DateTime object's datetime lies in the past.
21
- def past?
22
- self < ::DateTime.current
23
- end
24
-
25
- # Tells whether the DateTime object's datetime lies in the future.
26
- def future?
27
- self > ::DateTime.current
28
- end
29
-
30
13
  # Seconds since midnight: DateTime.now.seconds_since_midnight.
31
14
  def seconds_since_midnight
32
15
  sec + (min * 60) + (hour * 3600)
@@ -41,6 +24,13 @@ class DateTime
41
24
  end_of_day.to_i - to_i
42
25
  end
43
26
 
27
+ # Returns the fraction of a second as a +Rational+
28
+ #
29
+ # DateTime.new(2012, 8, 29, 0, 0, 0.5).subsec # => (1/2)
30
+ def subsec
31
+ sec_fraction
32
+ end
33
+
44
34
  # Returns a new DateTime where one or more of the elements have been changed
45
35
  # according to the +options+ parameter. The time options (<tt>:hour</tt>,
46
36
  # <tt>:min</tt>, <tt>:sec</tt>) reset cascadingly, so if only the hour is
@@ -70,6 +60,16 @@ class DateTime
70
60
  # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
71
61
  # <tt>:minutes</tt>, <tt>:seconds</tt>.
72
62
  def advance(options)
63
+ unless options[:weeks].nil?
64
+ options[:weeks], partial_weeks = options[:weeks].divmod(1)
65
+ options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
66
+ end
67
+
68
+ unless options[:days].nil?
69
+ options[:days], partial_days = options[:days].divmod(1)
70
+ options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
71
+ end
72
+
73
73
  d = to_date.advance(options)
74
74
  datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
75
75
  seconds_to_advance = \
@@ -80,7 +80,7 @@ class DateTime
80
80
  if seconds_to_advance.zero?
81
81
  datetime_advanced_by_date
82
82
  else
83
- datetime_advanced_by_date.since seconds_to_advance
83
+ datetime_advanced_by_date.since(seconds_to_advance)
84
84
  end
85
85
  end
86
86
 
@@ -106,6 +106,16 @@ class DateTime
106
106
  alias :at_midnight :beginning_of_day
107
107
  alias :at_beginning_of_day :beginning_of_day
108
108
 
109
+ # Returns a new DateTime representing the middle of the day (12:00)
110
+ def middle_of_day
111
+ change(:hour => 12)
112
+ end
113
+ alias :midday :middle_of_day
114
+ alias :noon :middle_of_day
115
+ alias :at_midday :middle_of_day
116
+ alias :at_noon :middle_of_day
117
+ alias :at_middle_of_day :middle_of_day
118
+
109
119
  # Returns a new DateTime representing the end of the day (23:59:59).
110
120
  def end_of_day
111
121
  change(:hour => 23, :min => 59, :sec => 59)
@@ -136,14 +146,27 @@ class DateTime
136
146
  end
137
147
  alias :at_end_of_minute :end_of_minute
138
148
 
139
- # Adjusts DateTime to UTC by adding its offset value; offset is set to 0.
149
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
150
+ def localtime(utc_offset = nil)
151
+ utc = new_offset(0)
152
+
153
+ Time.utc(
154
+ utc.year, utc.month, utc.day,
155
+ utc.hour, utc.min, utc.sec + utc.sec_fraction
156
+ ).getlocal(utc_offset)
157
+ end
158
+ alias_method :getlocal, :localtime
159
+
160
+ # Returns a <tt>DateTime</tt> instance of the simultaneous time in the UTC timezone.
140
161
  #
141
162
  # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
142
- # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
163
+ # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
143
164
  def utc
144
165
  new_offset(0)
145
166
  end
167
+ alias_method :getgm, :utc
146
168
  alias_method :getutc, :utc
169
+ alias_method :gmtime, :utc
147
170
 
148
171
  # Returns +true+ if <tt>offset == 0</tt>.
149
172
  def utc?
@@ -161,7 +184,7 @@ class DateTime
161
184
  if other.kind_of?(Infinity)
162
185
  super
163
186
  elsif other.respond_to? :to_datetime
164
- super other.to_datetime
187
+ super other.to_datetime rescue nil
165
188
  else
166
189
  nil
167
190
  end
@@ -0,0 +1,16 @@
1
+ require 'active_support/core_ext/date_and_time/compatibility'
2
+ require 'active_support/core_ext/module/remove_method'
3
+
4
+ class DateTime
5
+ include DateAndTime::Compatibility
6
+
7
+ remove_possible_method :to_time
8
+
9
+ # Either return an instance of `Time` with the same UTC offset
10
+ # as +self+ or an instance of `Time` representing the same time
11
+ # in the the local system timezone depending on the setting of
12
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
13
+ def to_time
14
+ preserve_timezone ? getlocal(utc_offset) : getlocal
15
+ end
16
+ end
@@ -1,3 +1,4 @@
1
+ require 'date'
1
2
  require 'active_support/inflector/methods'
2
3
  require 'active_support/core_ext/time/conversions'
3
4
  require 'active_support/core_ext/date_time/calculations'
@@ -18,6 +19,7 @@ class DateTime
18
19
  # datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
19
20
  # datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
20
21
  # datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
22
+ # datetime.to_formatted_s(:iso8601) # => "2007-12-04T00:00:00+00:00"
21
23
  #
22
24
  # == Adding your own datetime formats to to_formatted_s
23
25
  # DateTime formats are shared with Time. You can add your own to the
@@ -69,9 +71,9 @@ class DateTime
69
71
  civil(year, month, day, hour, min, sec, offset)
70
72
  end
71
73
 
72
- # Converts +self+ to a floating-point number of seconds since the Unix epoch.
74
+ # Converts +self+ to a floating-point number of seconds, including fractional microseconds, since the Unix epoch.
73
75
  def to_f
74
- seconds_since_unix_epoch.to_f
76
+ seconds_since_unix_epoch.to_f + sec_fraction
75
77
  end
76
78
 
77
79
  # Converts +self+ to an integer number of seconds since the Unix epoch.
@@ -1,24 +1,6 @@
1
- require 'active_support/core_ext/time/zones'
1
+ require 'date'
2
+ require 'active_support/core_ext/date_and_time/zones'
2
3
 
3
4
  class DateTime
4
- # Returns the simultaneous time in <tt>Time.zone</tt>.
5
- #
6
- # Time.zone = 'Hawaii' # => 'Hawaii'
7
- # DateTime.new(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
8
- #
9
- # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt>
10
- # as the local zone instead of the operating system's time zone.
11
- #
12
- # You can also pass in a TimeZone instance or string that identifies a TimeZone
13
- # as an argument, and the conversion will be based on that zone instead of
14
- # <tt>Time.zone</tt>.
15
- #
16
- # DateTime.new(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
17
- def in_time_zone(zone = ::Time.zone)
18
- if zone
19
- ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
20
- else
21
- self
22
- end
23
- end
5
+ include DateAndTime::Zones
24
6
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/core_ext/date_time/acts_like'
2
2
  require 'active_support/core_ext/date_time/calculations'
3
+ require 'active_support/core_ext/date_time/compatibility'
3
4
  require 'active_support/core_ext/date_time/conversions'
4
5
  require 'active_support/core_ext/date_time/zones'
@@ -0,0 +1,51 @@
1
+ require 'securerandom'
2
+
3
+ module Digest
4
+ module UUID
5
+ DNS_NAMESPACE = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
6
+ URL_NAMESPACE = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
7
+ OID_NAMESPACE = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
8
+ X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
9
+
10
+ # Generates a v5 non-random UUID (Universally Unique IDentifier).
11
+ #
12
+ # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
13
+ # uuid_from_hash always generates the same UUID for a given name and namespace combination.
14
+ #
15
+ # See RFC 4122 for details of UUID at: http://www.ietf.org/rfc/rfc4122.txt
16
+ def self.uuid_from_hash(hash_class, uuid_namespace, name)
17
+ if hash_class == Digest::MD5
18
+ version = 3
19
+ elsif hash_class == Digest::SHA1
20
+ version = 5
21
+ else
22
+ raise ArgumentError, "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
23
+ end
24
+
25
+ hash = hash_class.new
26
+ hash.update(uuid_namespace)
27
+ hash.update(name)
28
+
29
+ ary = hash.digest.unpack('NnnnnN')
30
+ ary[2] = (ary[2] & 0x0FFF) | (version << 12)
31
+ ary[3] = (ary[3] & 0x3FFF) | 0x8000
32
+
33
+ "%08x-%04x-%04x-%04x-%04x%08x" % ary
34
+ end
35
+
36
+ # Convenience method for uuid_from_hash using Digest::MD5.
37
+ def self.uuid_v3(uuid_namespace, name)
38
+ self.uuid_from_hash(Digest::MD5, uuid_namespace, name)
39
+ end
40
+
41
+ # Convenience method for uuid_from_hash using Digest::SHA1.
42
+ def self.uuid_v5(uuid_namespace, name)
43
+ self.uuid_from_hash(Digest::SHA1, uuid_namespace, name)
44
+ end
45
+
46
+ # Convenience method for SecureRandom.uuid.
47
+ def self.uuid_v4
48
+ SecureRandom.uuid
49
+ end
50
+ end
51
+ end
@@ -35,7 +35,7 @@ module Enumerable
35
35
  if block_given?
36
36
  Hash[map { |elem| [yield(elem), elem] }]
37
37
  else
38
- to_enum :index_by
38
+ to_enum(:index_by) { size if respond_to?(:size) }
39
39
  end
40
40
  end
41
41
 
@@ -78,3 +78,19 @@ class Range #:nodoc:
78
78
  end
79
79
  end
80
80
  end
81
+
82
+ # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
83
+ #
84
+ # We tried shimming it to attempt the fast native method, rescue TypeError,
85
+ # and fall back to the compatible implementation, but that's much slower than
86
+ # just calling the compat method in the first place.
87
+ if Array.instance_methods(false).include?(:sum) && !(%w[a].sum rescue false)
88
+ class Array
89
+ remove_method :sum
90
+
91
+ def sum(*args) #:nodoc:
92
+ # Use Enumerable#sum instead.
93
+ super
94
+ end
95
+ end
96
+ end
@@ -40,7 +40,7 @@ class File
40
40
  chown(old_stat.uid, old_stat.gid, file_name)
41
41
  # This operation will affect filesystem ACL's
42
42
  chmod(old_stat.mode, file_name)
43
- rescue Errno::EPERM
43
+ rescue Errno::EPERM, Errno::EACCES
44
44
  # Changing file ownership failed, moving on.
45
45
  end
46
46
  end
@@ -0,0 +1,24 @@
1
+ class Hash
2
+ unless Hash.instance_methods(false).include?(:compact)
3
+ # Returns a hash with non +nil+ values.
4
+ #
5
+ # hash = { a: true, b: false, c: nil}
6
+ # hash.compact # => { a: true, b: false}
7
+ # hash # => { a: true, b: false, c: nil}
8
+ # { c: nil }.compact # => {}
9
+ def compact
10
+ self.select { |_, value| !value.nil? }
11
+ end
12
+ end
13
+
14
+ unless Hash.instance_methods(false).include?(:compact!)
15
+ # Replaces current hash with non +nil+ values.
16
+ #
17
+ # hash = { a: true, b: false, c: nil}
18
+ # hash.compact! # => { a: true, b: false}
19
+ # hash # => { a: true, b: false}
20
+ def compact!
21
+ self.reject! { |_, value| value.nil? }
22
+ end
23
+ end
24
+ end
@@ -10,7 +10,7 @@ require 'active_support/core_ext/string/inflections'
10
10
  class Hash
11
11
  # Returns a string containing an XML representation of its receiver:
12
12
  #
13
- # {'foo' => 1, 'bar' => 2}.to_xml
13
+ # { foo: 1, bar: 2 }.to_xml
14
14
  # # =>
15
15
  # # <?xml version="1.0" encoding="UTF-8"?>
16
16
  # # <hash>
@@ -43,7 +43,10 @@ class Hash
43
43
  # end
44
44
  #
45
45
  # { foo: Foo.new }.to_xml(skip_instruct: true)
46
- # # => "<hash><bar>fooing!</bar></hash>"
46
+ # # =>
47
+ # # <hash>
48
+ # # <bar>fooing!</bar>
49
+ # # </hash>
47
50
  #
48
51
  # * Otherwise, a node with +key+ as tag is created with a string representation of
49
52
  # +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
@@ -52,8 +55,7 @@ class Hash
52
55
  #
53
56
  # XML_TYPE_NAMES = {
54
57
  # "Symbol" => "symbol",
55
- # "Fixnum" => "integer",
56
- # "Bignum" => "integer",
58
+ # "Integer" => "integer",
57
59
  # "BigDecimal" => "decimal",
58
60
  # "Float" => "float",
59
61
  # "TrueClass" => "boolean",
@@ -102,7 +104,7 @@ class Hash
102
104
  # hash = Hash.from_xml(xml)
103
105
  # # => {"hash"=>{"foo"=>1, "bar"=>2}}
104
106
  #
105
- # DisallowedType is raise if the XML contains attributes with <tt>type="yaml"</tt> or
107
+ # +DisallowedType+ is raised if the XML contains attributes with <tt>type="yaml"</tt> or
106
108
  # <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to parse this XML.
107
109
  def from_xml(xml, disallowed_types = nil)
108
110
  ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
@@ -201,7 +203,7 @@ module ActiveSupport
201
203
  end
202
204
 
203
205
  def become_empty_string?(value)
204
- # {"string" => true}
206
+ # { "string" => true }
205
207
  # No tests fail when the second term is removed.
206
208
  value['type'] == 'string' && value['nil'] != 'true'
207
209
  end
@@ -218,7 +220,7 @@ module ActiveSupport
218
220
  def garbage?(value)
219
221
  # If the type is the only element which makes it then
220
222
  # this still makes the value nil, except if type is
221
- # a XML node(where type['value'] is a Hash)
223
+ # an XML node(where type['value'] is a Hash)
222
224
  value['type'] && !value['type'].is_a?(::Hash) && value.size == 1
223
225
  end
224
226
 
@@ -238,4 +240,3 @@ module ActiveSupport
238
240
 
239
241
  end
240
242
  end
241
-
@@ -1,13 +1,19 @@
1
1
  class Hash
2
- # Return a hash that includes everything but the given keys. This is useful for
3
- # limiting a set of parameters to everything but a few known toggles:
2
+ # Returns a hash that includes everything but the given keys.
3
+ # hash = { a: true, b: false, c: nil}
4
+ # hash.except(:c) # => { a: true, b: false}
5
+ # hash # => { a: true, b: false, c: nil}
4
6
  #
7
+ # This is useful for limiting a set of parameters to everything but a few known toggles:
5
8
  # @person.update(params[:person].except(:admin))
6
9
  def except(*keys)
7
10
  dup.except!(*keys)
8
11
  end
9
12
 
10
13
  # Replaces the hash without the given keys.
14
+ # hash = { a: true, b: false, c: nil}
15
+ # hash.except!(:c) # => { a: true, b: false}
16
+ # hash # => { a: true, b: false }
11
17
  def except!(*keys)
12
18
  keys.each { |key| delete(key) }
13
19
  self
@@ -18,5 +18,6 @@ class Hash
18
18
  #
19
19
  # b = { b: 1 }
20
20
  # { a: b }.with_indifferent_access['a'] # calls b.nested_under_indifferent_access
21
+ # # => {"b"=>1}
21
22
  alias nested_under_indifferent_access with_indifferent_access
22
23
  end