activesupport 4.2.0 → 5.2.0

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 (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +54 -21
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration.rb +326 -30
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,5 +1,7 @@
1
- require 'date'
2
- require 'active_support/core_ext/object/acts_like'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/core_ext/object/acts_like"
3
5
 
4
6
  class DateTime
5
7
  # Duck-types as a Date-like class. See Object#acts_like?.
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ class DateTime #:nodoc:
6
+ # No DateTime is ever blank:
7
+ #
8
+ # DateTime.now.blank? # => false
9
+ #
10
+ # @return [false]
11
+ def blank?
12
+ false
13
+ end
14
+ end
@@ -1,4 +1,6 @@
1
- require 'date'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
2
4
 
3
5
  class DateTime
4
6
  class << self
@@ -10,7 +12,11 @@ class DateTime
10
12
  end
11
13
  end
12
14
 
13
- # Seconds since midnight: DateTime.now.seconds_since_midnight.
15
+ # Returns the number of seconds since 00:00:00.
16
+ #
17
+ # DateTime.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0
18
+ # DateTime.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296
19
+ # DateTime.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399
14
20
  def seconds_since_midnight
15
21
  sec + (min * 60) + (hour * 3600)
16
22
  end
@@ -24,6 +30,13 @@ class DateTime
24
30
  end_of_day.to_i - to_i
25
31
  end
26
32
 
33
+ # Returns the fraction of a second as a +Rational+
34
+ #
35
+ # DateTime.new(2012, 8, 29, 0, 0, 0.5).subsec # => (1/2)
36
+ def subsec
37
+ sec_fraction
38
+ end
39
+
27
40
  # Returns a new DateTime where one or more of the elements have been changed
28
41
  # according to the +options+ parameter. The time options (<tt>:hour</tt>,
29
42
  # <tt>:min</tt>, <tt>:sec</tt>) reset cascadingly, so if only the hour is
@@ -36,13 +49,23 @@ class DateTime
36
49
  # DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => DateTime.new(1981, 8, 1, 22, 35, 0)
37
50
  # DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
38
51
  def change(options)
52
+ if new_nsec = options[:nsec]
53
+ raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
54
+ new_fraction = Rational(new_nsec, 1000000000)
55
+ else
56
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
57
+ new_fraction = Rational(new_usec, 1000000)
58
+ end
59
+
60
+ raise ArgumentError, "argument out of range" if new_fraction >= 1
61
+
39
62
  ::DateTime.civil(
40
63
  options.fetch(:year, year),
41
64
  options.fetch(:month, month),
42
65
  options.fetch(:day, day),
43
66
  options.fetch(:hour, hour),
44
67
  options.fetch(:min, options[:hour] ? 0 : min),
45
- options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec + sec_fraction),
68
+ options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
46
69
  options.fetch(:offset, offset),
47
70
  options.fetch(:start, start)
48
71
  )
@@ -64,7 +87,7 @@ class DateTime
64
87
  end
65
88
 
66
89
  d = to_date.advance(options)
67
- datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
90
+ datetime_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
68
91
  seconds_to_advance = \
69
92
  options.fetch(:seconds, 0) +
70
93
  options.fetch(:minutes, 0) * 60 +
@@ -93,7 +116,7 @@ class DateTime
93
116
 
94
117
  # Returns a new DateTime representing the start of the day (0:00).
95
118
  def beginning_of_day
96
- change(:hour => 0)
119
+ change(hour: 0)
97
120
  end
98
121
  alias :midnight :beginning_of_day
99
122
  alias :at_midnight :beginning_of_day
@@ -101,7 +124,7 @@ class DateTime
101
124
 
102
125
  # Returns a new DateTime representing the middle of the day (12:00)
103
126
  def middle_of_day
104
- change(:hour => 12)
127
+ change(hour: 12)
105
128
  end
106
129
  alias :midday :middle_of_day
107
130
  alias :noon :middle_of_day
@@ -111,42 +134,60 @@ class DateTime
111
134
 
112
135
  # Returns a new DateTime representing the end of the day (23:59:59).
113
136
  def end_of_day
114
- change(:hour => 23, :min => 59, :sec => 59)
137
+ change(hour: 23, min: 59, sec: 59, usec: Rational(999999999, 1000))
115
138
  end
116
139
  alias :at_end_of_day :end_of_day
117
140
 
118
141
  # Returns a new DateTime representing the start of the hour (hh:00:00).
119
142
  def beginning_of_hour
120
- change(:min => 0)
143
+ change(min: 0)
121
144
  end
122
145
  alias :at_beginning_of_hour :beginning_of_hour
123
146
 
124
147
  # Returns a new DateTime representing the end of the hour (hh:59:59).
125
148
  def end_of_hour
126
- change(:min => 59, :sec => 59)
149
+ change(min: 59, sec: 59, usec: Rational(999999999, 1000))
127
150
  end
128
151
  alias :at_end_of_hour :end_of_hour
129
152
 
130
153
  # Returns a new DateTime representing the start of the minute (hh:mm:00).
131
154
  def beginning_of_minute
132
- change(:sec => 0)
155
+ change(sec: 0)
133
156
  end
134
157
  alias :at_beginning_of_minute :beginning_of_minute
135
158
 
136
159
  # Returns a new DateTime representing the end of the minute (hh:mm:59).
137
160
  def end_of_minute
138
- change(:sec => 59)
161
+ change(sec: 59, usec: Rational(999999999, 1000))
139
162
  end
140
163
  alias :at_end_of_minute :end_of_minute
141
164
 
142
- # Adjusts DateTime to UTC by adding its offset value; offset is set to 0.
165
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
166
+ def localtime(utc_offset = nil)
167
+ utc = new_offset(0)
168
+
169
+ Time.utc(
170
+ utc.year, utc.month, utc.day,
171
+ utc.hour, utc.min, utc.sec + utc.sec_fraction
172
+ ).getlocal(utc_offset)
173
+ end
174
+ alias_method :getlocal, :localtime
175
+
176
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
143
177
  #
144
178
  # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
145
- # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 +0000
179
+ # DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
146
180
  def utc
147
- new_offset(0)
181
+ utc = new_offset(0)
182
+
183
+ Time.utc(
184
+ utc.year, utc.month, utc.day,
185
+ utc.hour, utc.min, utc.sec + utc.sec_fraction
186
+ )
148
187
  end
188
+ alias_method :getgm, :utc
149
189
  alias_method :getutc, :utc
190
+ alias_method :gmtime, :utc
150
191
 
151
192
  # Returns +true+ if <tt>offset == 0</tt>.
152
193
  def utc?
@@ -161,13 +202,10 @@ class DateTime
161
202
  # Layers additional behavior on DateTime#<=> so that Time and
162
203
  # ActiveSupport::TimeWithZone instances can be compared with a DateTime.
163
204
  def <=>(other)
164
- if other.kind_of?(Infinity)
165
- super
166
- elsif other.respond_to? :to_datetime
167
- super other.to_datetime
205
+ if other.respond_to? :to_datetime
206
+ super other.to_datetime rescue nil
168
207
  else
169
- nil
208
+ super
170
209
  end
171
210
  end
172
-
173
211
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/date_and_time/compatibility"
4
+ require "active_support/core_ext/module/redefine_method"
5
+
6
+ class DateTime
7
+ include DateAndTime::Compatibility
8
+
9
+ silence_redefinition_of_method :to_time
10
+
11
+ # Either return an instance of +Time+ with the same UTC offset
12
+ # as +self+ or an instance of +Time+ representing the same time
13
+ # in the local system timezone depending on the setting of
14
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
15
+ def to_time
16
+ preserve_timezone ? getlocal(utc_offset) : getlocal
17
+ end
18
+ end
@@ -1,8 +1,10 @@
1
- require 'date'
2
- require 'active_support/inflector/methods'
3
- require 'active_support/core_ext/time/conversions'
4
- require 'active_support/core_ext/date_time/calculations'
5
- require 'active_support/values/time_zone'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/inflector/methods"
5
+ require "active_support/core_ext/time/conversions"
6
+ require "active_support/core_ext/date_time/calculations"
7
+ require "active_support/values/time_zone"
6
8
 
7
9
  class DateTime
8
10
  # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
@@ -40,6 +42,8 @@ class DateTime
40
42
  alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
41
43
  alias_method :to_s, :to_formatted_s
42
44
 
45
+ # Returns a formatted string of the offset from UTC, or an alternative
46
+ # string if the time zone is already UTC.
43
47
  #
44
48
  # datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
45
49
  # datetime.formatted_offset # => "-06:00"
@@ -62,7 +66,7 @@ class DateTime
62
66
  # # => Sun, 01 Jan 2012 00:00:00 +0300
63
67
  # DateTime.civil_from_format :local, 2012, 12, 17
64
68
  # # => Mon, 17 Dec 2012 00:00:00 +0000
65
- def self.civil_from_format(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0)
69
+ def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)
66
70
  if utc_or_local.to_sym == :local
67
71
  offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
68
72
  else
@@ -93,11 +97,11 @@ class DateTime
93
97
 
94
98
  private
95
99
 
96
- def offset_in_seconds
97
- (offset * 86400).to_i
98
- end
100
+ def offset_in_seconds
101
+ (offset * 86400).to_i
102
+ end
99
103
 
100
- def seconds_since_unix_epoch
101
- (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
102
- end
104
+ def seconds_since_unix_epoch
105
+ (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
106
+ end
103
107
  end
@@ -1,4 +1,6 @@
1
- require 'securerandom'
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
2
4
 
3
5
  module Digest
4
6
  module UUID
@@ -12,7 +14,7 @@ module Digest
12
14
  # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
13
15
  # uuid_from_hash always generates the same UUID for a given name and namespace combination.
14
16
  #
15
- # See RFC 4122 for details of UUID at: http://www.ietf.org/rfc/rfc4122.txt
17
+ # See RFC 4122 for details of UUID at: https://www.ietf.org/rfc/rfc4122.txt
16
18
  def self.uuid_from_hash(hash_class, uuid_namespace, name)
17
19
  if hash_class == Digest::MD5
18
20
  version = 3
@@ -26,7 +28,7 @@ module Digest
26
28
  hash.update(uuid_namespace)
27
29
  hash.update(name)
28
30
 
29
- ary = hash.digest.unpack('NnnnnN')
31
+ ary = hash.digest.unpack("NnnnnN")
30
32
  ary[2] = (ary[2] & 0x0FFF) | (version << 12)
31
33
  ary[3] = (ary[3] & 0x3FFF) | 0x8000
32
34
 
@@ -35,12 +37,12 @@ module Digest
35
37
 
36
38
  # Convenience method for uuid_from_hash using Digest::MD5.
37
39
  def self.uuid_v3(uuid_namespace, name)
38
- self.uuid_from_hash(Digest::MD5, uuid_namespace, name)
40
+ uuid_from_hash(Digest::MD5, uuid_namespace, name)
39
41
  end
40
42
 
41
43
  # Convenience method for uuid_from_hash using Digest::SHA1.
42
44
  def self.uuid_v5(uuid_namespace, name)
43
- self.uuid_from_hash(Digest::SHA1, uuid_namespace, name)
45
+ uuid_from_hash(Digest::SHA1, uuid_namespace, name)
44
46
  end
45
47
 
46
48
  # Convenience method for SecureRandom.uuid.
@@ -1,39 +1,66 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerable
2
- # Calculates a sum from the elements.
3
- #
4
- # payments.sum { |p| p.price * p.tax_rate }
5
- # payments.sum(&:price)
6
- #
7
- # The latter is a shortcut for:
8
- #
9
- # payments.inject(0) { |sum, p| sum + p.price }
4
+ # Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
5
+ # when we omit an identity.
10
6
  #
11
- # It can also calculate the sum without the use of a block.
12
- #
13
- # [5, 15, 10].sum # => 30
14
- # ['foo', 'bar'].sum # => "foobar"
15
- # [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
16
- #
17
- # The default sum of an empty list is zero. You can override this default:
18
- #
19
- # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
20
- def sum(identity = 0, &block)
21
- if block_given?
22
- map(&block).sum(identity)
23
- else
24
- inject { |sum, element| sum + element } || identity
7
+ # We tried shimming it to attempt the fast native method, rescue TypeError,
8
+ # and fall back to the compatible implementation, but that's much slower than
9
+ # just calling the compat method in the first place.
10
+ if Enumerable.instance_methods(false).include?(:sum) && !((?a..?b).sum rescue false)
11
+ # We can't use Refinements here because Refinements with Module which will be prepended
12
+ # doesn't work well https://bugs.ruby-lang.org/issues/13446
13
+ alias :_original_sum_with_required_identity :sum
14
+ private :_original_sum_with_required_identity
15
+ # Calculates a sum from the elements.
16
+ #
17
+ # payments.sum { |p| p.price * p.tax_rate }
18
+ # payments.sum(&:price)
19
+ #
20
+ # The latter is a shortcut for:
21
+ #
22
+ # payments.inject(0) { |sum, p| sum + p.price }
23
+ #
24
+ # It can also calculate the sum without the use of a block.
25
+ #
26
+ # [5, 15, 10].sum # => 30
27
+ # ['foo', 'bar'].sum # => "foobar"
28
+ # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
29
+ #
30
+ # The default sum of an empty list is zero. You can override this default:
31
+ #
32
+ # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
33
+ def sum(identity = nil, &block)
34
+ if identity
35
+ _original_sum_with_required_identity(identity, &block)
36
+ elsif block_given?
37
+ map(&block).sum(identity)
38
+ else
39
+ inject(:+) || 0
40
+ end
41
+ end
42
+ else
43
+ def sum(identity = nil, &block)
44
+ if block_given?
45
+ map(&block).sum(identity)
46
+ else
47
+ sum = identity ? inject(identity, :+) : inject(:+)
48
+ sum || identity || 0
49
+ end
25
50
  end
26
51
  end
27
52
 
28
53
  # Convert an enumerable to a hash.
29
54
  #
30
55
  # people.index_by(&:login)
31
- # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
56
+ # # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
32
57
  # people.index_by { |person| "#{person.first_name} #{person.last_name}" }
33
- # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
58
+ # # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
34
59
  def index_by
35
60
  if block_given?
36
- Hash[map { |elem| [yield(elem), elem] }]
61
+ result = {}
62
+ each { |elem| result[yield(elem)] = elem }
63
+ result
37
64
  else
38
65
  to_enum(:index_by) { size if respond_to?(:size) }
39
66
  end
@@ -60,20 +87,72 @@ module Enumerable
60
87
  def exclude?(object)
61
88
  !include?(object)
62
89
  end
90
+
91
+ # Returns a copy of the enumerable without the specified elements.
92
+ #
93
+ # ["David", "Rafael", "Aaron", "Todd"].without "Aaron", "Todd"
94
+ # # => ["David", "Rafael"]
95
+ #
96
+ # {foo: 1, bar: 2, baz: 3}.without :bar
97
+ # # => {foo: 1, baz: 3}
98
+ def without(*elements)
99
+ reject { |element| elements.include?(element) }
100
+ end
101
+
102
+ # Convert an enumerable to an array based on the given key.
103
+ #
104
+ # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
105
+ # # => ["David", "Rafael", "Aaron"]
106
+ #
107
+ # [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)
108
+ # # => [[1, "David"], [2, "Rafael"]]
109
+ def pluck(*keys)
110
+ if keys.many?
111
+ map { |element| keys.map { |key| element[key] } }
112
+ else
113
+ map { |element| element[keys.first] }
114
+ end
115
+ end
63
116
  end
64
117
 
65
118
  class Range #:nodoc:
66
119
  # Optimize range sum to use arithmetic progression if a block is not given and
67
120
  # we have a range of numeric values.
68
- def sum(identity = 0)
121
+ def sum(identity = nil)
69
122
  if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
70
123
  super
71
124
  else
72
125
  actual_last = exclude_end? ? (last - 1) : last
73
126
  if actual_last >= first
74
- (actual_last - first + 1) * (actual_last + first) / 2
127
+ sum = identity || 0
128
+ sum + (actual_last - first + 1) * (actual_last + first) / 2
129
+ else
130
+ identity || 0
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
137
+ #
138
+ # We tried shimming it to attempt the fast native method, rescue TypeError,
139
+ # and fall back to the compatible implementation, but that's much slower than
140
+ # just calling the compat method in the first place.
141
+ if Array.instance_methods(false).include?(:sum) && !(%w[a].sum rescue false)
142
+ # Using Refinements here in order not to expose our internal method
143
+ using Module.new {
144
+ refine Array do
145
+ alias :orig_sum :sum
146
+ end
147
+ }
148
+
149
+ class Array
150
+ def sum(init = nil, &block) #:nodoc:
151
+ if init.is_a?(Numeric) || first.is_a?(Numeric)
152
+ init ||= 0
153
+ orig_sum(init, &block)
75
154
  else
76
- identity
155
+ super
77
156
  end
78
157
  end
79
158
  end