activesupport 5.1.7 → 6.1.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (262) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +434 -490
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +6 -2
  8. data/lib/active_support/backtrace_cleaner.rb +31 -3
  9. data/lib/active_support/benchmarkable.rb +3 -1
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache/file_store.rb +37 -36
  12. data/lib/active_support/cache/mem_cache_store.rb +72 -56
  13. data/lib/active_support/cache/memory_store.rb +61 -33
  14. data/lib/active_support/cache/null_store.rb +10 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +67 -21
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  18. data/lib/active_support/cache.rb +310 -126
  19. data/lib/active_support/callbacks.rb +106 -100
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  22. data/lib/active_support/concurrency/share_lock.rb +2 -1
  23. data/lib/active_support/configurable.rb +12 -14
  24. data/lib/active_support/configuration_file.rb +51 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +7 -5
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +2 -0
  30. data/lib/active_support/core_ext/array/inquiry.rb +2 -0
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +3 -1
  33. data/lib/active_support/core_ext/benchmark.rb +4 -2
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
  35. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +50 -47
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -40
  39. data/lib/active_support/core_ext/class.rb +2 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  41. data/lib/active_support/core_ext/date/blank.rb +2 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +8 -5
  43. data/lib/active_support/core_ext/date/conversions.rb +12 -10
  44. data/lib/active_support/core_ext/date/zones.rb +2 -0
  45. data/lib/active_support/core_ext/date.rb +2 -0
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +2 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  53. data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
  54. data/lib/active_support/core_ext/date_time.rb +2 -0
  55. data/lib/active_support/core_ext/digest/uuid.rb +4 -1
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +174 -71
  58. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  59. data/lib/active_support/core_ext/file.rb +2 -0
  60. data/lib/active_support/core_ext/hash/conversions.rb +7 -5
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
  65. data/lib/active_support/core_ext/hash/keys.rb +3 -30
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +3 -2
  69. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +7 -14
  72. data/lib/active_support/core_ext/integer.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  74. data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +2 -1
  77. data/lib/active_support/core_ext/load_error.rb +3 -8
  78. data/lib/active_support/core_ext/marshal.rb +4 -0
  79. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
  84. data/lib/active_support/core_ext/module/concerning.rb +15 -10
  85. data/lib/active_support/core_ext/module/delegation.rb +103 -58
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +18 -15
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +3 -1
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
  94. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  95. data/lib/active_support/core_ext/numeric.rb +2 -1
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +13 -3
  98. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  99. data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
  100. data/lib/active_support/core_ext/object/duplicable.rb +9 -114
  101. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +22 -2
  104. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  105. data/lib/active_support/core_ext/object/to_query.rb +2 -0
  106. data/lib/active_support/core_ext/object/try.rb +19 -7
  107. data/lib/active_support/core_ext/object/with_options.rb +4 -2
  108. data/lib/active_support/core_ext/object.rb +2 -0
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +4 -1
  115. data/lib/active_support/core_ext/regexp.rb +10 -5
  116. data/lib/active_support/core_ext/securerandom.rb +25 -3
  117. data/lib/active_support/core_ext/string/access.rb +7 -16
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +3 -0
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +44 -1
  122. data/lib/active_support/core_ext/string/indent.rb +2 -0
  123. data/lib/active_support/core_ext/string/inflections.rb +69 -16
  124. data/lib/active_support/core_ext/string/inquiry.rb +3 -0
  125. data/lib/active_support/core_ext/string/multibyte.rb +9 -4
  126. data/lib/active_support/core_ext/string/output_safety.rb +104 -20
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  129. data/lib/active_support/core_ext/string/zones.rb +2 -0
  130. data/lib/active_support/core_ext/string.rb +2 -0
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  134. data/lib/active_support/core_ext/time/calculations.rb +76 -18
  135. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +4 -0
  137. data/lib/active_support/core_ext/time/zones.rb +6 -4
  138. data/lib/active_support/core_ext/time.rb +2 -0
  139. data/lib/active_support/core_ext/uri.rb +11 -6
  140. data/lib/active_support/core_ext.rb +3 -1
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +210 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +2 -0
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
  146. data/lib/active_support/dependencies.rb +134 -60
  147. data/lib/active_support/deprecation/behaviors.rb +43 -11
  148. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +2 -1
  151. data/lib/active_support/deprecation/method_wrappers.rb +29 -21
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
  153. data/lib/active_support/deprecation/reporting.rb +54 -9
  154. data/lib/active_support/deprecation.rb +9 -2
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +22 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +6 -6
  158. data/lib/active_support/duration/iso8601_serializer.rb +20 -14
  159. data/lib/active_support/duration.rb +102 -45
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +84 -117
  164. data/lib/active_support/execution_wrapper.rb +19 -13
  165. data/lib/active_support/executor.rb +2 -0
  166. data/lib/active_support/file_update_checker.rb +2 -1
  167. data/lib/active_support/fork_tracker.rb +64 -0
  168. data/lib/active_support/gem_version.rb +3 -1
  169. data/lib/active_support/gzip.rb +2 -0
  170. data/lib/active_support/hash_with_indifferent_access.rb +123 -41
  171. data/lib/active_support/i18n.rb +4 -1
  172. data/lib/active_support/i18n_railtie.rb +19 -14
  173. data/lib/active_support/inflections.rb +2 -0
  174. data/lib/active_support/inflector/inflections.rb +19 -8
  175. data/lib/active_support/inflector/methods.rb +87 -77
  176. data/lib/active_support/inflector/transliterate.rb +56 -18
  177. data/lib/active_support/inflector.rb +2 -0
  178. data/lib/active_support/json/decoding.rb +27 -26
  179. data/lib/active_support/json/encoding.rb +13 -3
  180. data/lib/active_support/json.rb +2 -0
  181. data/lib/active_support/key_generator.rb +3 -33
  182. data/lib/active_support/lazy_load_hooks.rb +7 -2
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +2 -0
  186. data/lib/active_support/log_subscriber.rb +42 -11
  187. data/lib/active_support/logger.rb +4 -17
  188. data/lib/active_support/logger_silence.rb +13 -20
  189. data/lib/active_support/logger_thread_safe_level.rb +54 -7
  190. data/lib/active_support/message_encryptor.rb +100 -32
  191. data/lib/active_support/message_verifier.rb +85 -14
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +12 -68
  196. data/lib/active_support/multibyte/unicode.rb +17 -327
  197. data/lib/active_support/multibyte.rb +2 -0
  198. data/lib/active_support/notifications/fanout.rb +118 -16
  199. data/lib/active_support/notifications/instrumenter.rb +73 -9
  200. data/lib/active_support/notifications.rb +74 -8
  201. data/lib/active_support/number_helper/number_converter.rb +7 -6
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
  209. data/lib/active_support/number_helper/rounding_helper.rb +16 -30
  210. data/lib/active_support/number_helper.rb +40 -12
  211. data/lib/active_support/option_merger.rb +24 -3
  212. data/lib/active_support/ordered_hash.rb +3 -1
  213. data/lib/active_support/ordered_options.rb +17 -5
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +4 -1
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +3 -10
  218. data/lib/active_support/railtie.rb +60 -9
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +7 -6
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +6 -3
  224. data/lib/active_support/subscriber.rb +74 -24
  225. data/lib/active_support/tagged_logging.rb +44 -8
  226. data/lib/active_support/test_case.rb +94 -2
  227. data/lib/active_support/testing/assertions.rb +58 -20
  228. data/lib/active_support/testing/autorun.rb +2 -0
  229. data/lib/active_support/testing/constant_lookup.rb +2 -0
  230. data/lib/active_support/testing/declarative.rb +2 -0
  231. data/lib/active_support/testing/deprecation.rb +2 -1
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +4 -2
  234. data/lib/active_support/testing/method_call_assertions.rb +30 -1
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +12 -7
  239. data/lib/active_support/testing/stream.rb +3 -2
  240. data/lib/active_support/testing/tagged_logging.rb +2 -0
  241. data/lib/active_support/testing/time_helpers.rb +78 -13
  242. data/lib/active_support/time.rb +2 -0
  243. data/lib/active_support/time_with_zone.rb +113 -41
  244. data/lib/active_support/values/time_zone.rb +54 -25
  245. data/lib/active_support/version.rb +2 -0
  246. data/lib/active_support/xml_mini/jdom.rb +5 -4
  247. data/lib/active_support/xml_mini/libxml.rb +4 -2
  248. data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
  249. data/lib/active_support/xml_mini/nokogiri.rb +4 -2
  250. data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
  251. data/lib/active_support/xml_mini/rexml.rb +12 -3
  252. data/lib/active_support/xml_mini.rb +5 -11
  253. data/lib/active_support.rb +18 -13
  254. metadata +71 -32
  255. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  256. data/lib/active_support/core_ext/hash/compact.rb +0 -27
  257. data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
  258. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  259. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  260. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  261. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  262. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,15 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/object/try"
4
+ require "active_support/core_ext/date_time/conversions"
2
5
 
3
6
  module DateAndTime
4
7
  module Calculations
5
8
  DAYS_INTO_WEEK = {
6
- monday: 0,
7
- tuesday: 1,
8
- wednesday: 2,
9
- thursday: 3,
10
- friday: 4,
11
- saturday: 5,
12
- sunday: 6
9
+ sunday: 0,
10
+ monday: 1,
11
+ tuesday: 2,
12
+ wednesday: 3,
13
+ thursday: 4,
14
+ friday: 5,
15
+ saturday: 6
13
16
  }
14
17
  WEEKEND_DAYS = [ 6, 0 ]
15
18
 
@@ -18,26 +21,28 @@ module DateAndTime
18
21
  advance(days: -1)
19
22
  end
20
23
 
21
- # Returns a new date/time representing the previous day.
22
- def prev_day
23
- advance(days: -1)
24
- end
25
-
26
24
  # Returns a new date/time representing tomorrow.
27
25
  def tomorrow
28
26
  advance(days: 1)
29
27
  end
30
28
 
31
- # Returns a new date/time representing the next day.
32
- def next_day
33
- advance(days: 1)
34
- end
35
-
36
29
  # Returns true if the date/time is today.
37
30
  def today?
38
31
  to_date == ::Date.current
39
32
  end
40
33
 
34
+ # Returns true if the date/time is tomorrow.
35
+ def tomorrow?
36
+ to_date == ::Date.current.tomorrow
37
+ end
38
+ alias :next_day? :tomorrow?
39
+
40
+ # Returns true if the date/time is yesterday.
41
+ def yesterday?
42
+ to_date == ::Date.current.yesterday
43
+ end
44
+ alias :prev_day? :yesterday?
45
+
41
46
  # Returns true if the date/time is in the past.
42
47
  def past?
43
48
  self < self.class.current
@@ -58,6 +63,16 @@ module DateAndTime
58
63
  !WEEKEND_DAYS.include?(wday)
59
64
  end
60
65
 
66
+ # Returns true if the date/time falls before <tt>date_or_time</tt>.
67
+ def before?(date_or_time)
68
+ self < date_or_time
69
+ end
70
+
71
+ # Returns true if the date/time falls after <tt>date_or_time</tt>.
72
+ def after?(date_or_time)
73
+ self > date_or_time
74
+ end
75
+
61
76
  # Returns a new date/time the specified number of days ago.
62
77
  def days_ago(days)
63
78
  advance(days: -days)
@@ -122,7 +137,7 @@ module DateAndTime
122
137
  # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
123
138
  # now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
124
139
  def beginning_of_quarter
125
- first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
140
+ first_quarter_month = month - (2 + month) % 3
126
141
  beginning_of_month.change(month: first_quarter_month)
127
142
  end
128
143
  alias :at_beginning_of_quarter :beginning_of_quarter
@@ -137,7 +152,7 @@ module DateAndTime
137
152
  # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
138
153
  # now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
139
154
  def end_of_quarter
140
- last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
155
+ last_quarter_month = month + (12 - month) % 3
141
156
  beginning_of_month.change(month: last_quarter_month).end_of_month
142
157
  end
143
158
  alias :at_end_of_quarter :end_of_quarter
@@ -186,21 +201,11 @@ module DateAndTime
186
201
  end
187
202
  end
188
203
 
189
- # Short-hand for months_since(1).
190
- def next_month
191
- months_since(1)
192
- end
193
-
194
204
  # Short-hand for months_since(3)
195
205
  def next_quarter
196
206
  months_since(3)
197
207
  end
198
208
 
199
- # Short-hand for years_since(1).
200
- def next_year
201
- years_since(1)
202
- end
203
-
204
209
  # Returns a new date/time representing the given day in the previous week.
205
210
  # Week is assumed to start on +start_day+, default is
206
211
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
@@ -222,10 +227,9 @@ module DateAndTime
222
227
  alias_method :last_weekday, :prev_weekday
223
228
 
224
229
  # Short-hand for months_ago(1).
225
- def prev_month
230
+ def last_month
226
231
  months_ago(1)
227
232
  end
228
- alias_method :last_month, :prev_month
229
233
 
230
234
  # Short-hand for months_ago(3).
231
235
  def prev_quarter
@@ -234,18 +238,16 @@ module DateAndTime
234
238
  alias_method :last_quarter, :prev_quarter
235
239
 
236
240
  # Short-hand for years_ago(1).
237
- def prev_year
241
+ def last_year
238
242
  years_ago(1)
239
243
  end
240
- alias_method :last_year, :prev_year
241
244
 
242
245
  # Returns the number of days to the start of the week on the given day.
243
246
  # Week is assumed to start on +start_day+, default is
244
247
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
245
248
  def days_to_week_start(start_day = Date.beginning_of_week)
246
- start_day_number = DAYS_INTO_WEEK[start_day]
247
- current_day_number = wday != 0 ? wday - 1 : 6
248
- (current_day_number - start_day_number) % 7
249
+ start_day_number = DAYS_INTO_WEEK.fetch(start_day)
250
+ (wday - start_day_number) % 7
249
251
  end
250
252
 
251
253
  # Returns a new date/time representing the start of this week on the given day.
@@ -320,6 +322,28 @@ module DateAndTime
320
322
  beginning_of_year..end_of_year
321
323
  end
322
324
 
325
+ # Returns a new date/time representing the next occurrence of the specified day of week.
326
+ #
327
+ # today = Date.today # => Thu, 14 Dec 2017
328
+ # today.next_occurring(:monday) # => Mon, 18 Dec 2017
329
+ # today.next_occurring(:thursday) # => Thu, 21 Dec 2017
330
+ def next_occurring(day_of_week)
331
+ from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
332
+ from_now += 7 unless from_now > 0
333
+ advance(days: from_now)
334
+ end
335
+
336
+ # Returns a new date/time representing the previous occurrence of the specified day of week.
337
+ #
338
+ # today = Date.today # => Thu, 14 Dec 2017
339
+ # today.prev_occurring(:monday) # => Mon, 11 Dec 2017
340
+ # today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
341
+ def prev_occurring(day_of_week)
342
+ ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
343
+ ago += 7 unless ago > 0
344
+ advance(days: -ago)
345
+ end
346
+
323
347
  private
324
348
  def first_hour(date_or_time)
325
349
  date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
@@ -330,7 +354,7 @@ module DateAndTime
330
354
  end
331
355
 
332
356
  def days_span(day)
333
- (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
357
+ (DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
334
358
  end
335
359
 
336
360
  def copy_time_to(other)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/attribute_accessors"
2
4
 
3
5
  module DateAndTime
@@ -9,6 +11,21 @@ module DateAndTime
9
11
  # of the receiver. For backwards compatibility we're overriding
10
12
  # this behavior, but new apps will have an initializer that sets
11
13
  # this to true, because the new behavior is preferred.
12
- mattr_accessor(:preserve_timezone, instance_writer: false) { false }
14
+ mattr_accessor :preserve_timezone, instance_writer: false, default: false
15
+
16
+ # Change the output of <tt>ActiveSupport::TimeZone.utc_to_local</tt>.
17
+ #
18
+ # When `true`, it returns local times with an UTC offset, with `false` local
19
+ # times are returned as UTC.
20
+ #
21
+ # # Given this zone:
22
+ # zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
23
+ #
24
+ # # With `utc_to_local_returns_utc_offset_times = false`, local time is converted to UTC:
25
+ # zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 UTC
26
+ #
27
+ # # With `utc_to_local_returns_utc_offset_times = true`, local time is returned with UTC offset:
28
+ # zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 -0500
29
+ mattr_accessor :utc_to_local_returns_utc_offset_times, instance_writer: false, default: false
13
30
  end
14
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DateAndTime
2
4
  module Zones
3
5
  # Returns the simultaneous time in <tt>Time.zone</tt> if a zone is given or
@@ -27,7 +29,6 @@ module DateAndTime
27
29
  end
28
30
 
29
31
  private
30
-
31
32
  def time_with_zone(time, zone)
32
33
  if time
33
34
  ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "date"
2
4
  require "active_support/core_ext/object/acts_like"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "date"
2
4
 
3
5
  class DateTime #:nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "date"
2
4
 
3
5
  class DateTime
@@ -108,7 +110,7 @@ class DateTime
108
110
  # instance time. Do not use this method in combination with x.months, use
109
111
  # months_since instead!
110
112
  def since(seconds)
111
- self + Rational(seconds.round, 86400)
113
+ self + Rational(seconds, 86400)
112
114
  end
113
115
  alias :in :since
114
116
 
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/date_and_time/compatibility"
2
- require "active_support/core_ext/module/remove_method"
4
+ require "active_support/core_ext/module/redefine_method"
3
5
 
4
6
  class DateTime
5
7
  include DateAndTime::Compatibility
6
8
 
7
- remove_possible_method :to_time
9
+ silence_redefinition_of_method :to_time
8
10
 
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
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
12
14
  # on the setting of +ActiveSupport.to_time_preserves_timezone+.
13
15
  def to_time
14
16
  preserve_timezone ? getlocal(utc_offset) : getlocal
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "date"
2
4
  require "active_support/inflector/methods"
3
5
  require "active_support/core_ext/time/conversions"
@@ -94,7 +96,6 @@ class DateTime
94
96
  end
95
97
 
96
98
  private
97
-
98
99
  def offset_in_seconds
99
100
  (offset * 86400).to_i
100
101
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/date_time/acts_like"
2
4
  require "active_support/core_ext/date_time/blank"
3
5
  require "active_support/core_ext/date_time/calculations"
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "securerandom"
4
+ require "digest"
2
5
 
3
6
  module Digest
4
7
  module UUID
@@ -12,7 +15,7 @@ module Digest
12
15
  # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
13
16
  # uuid_from_hash always generates the same UUID for a given name and namespace combination.
14
17
  #
15
- # See RFC 4122 for details of UUID at: http://www.ietf.org/rfc/rfc4122.txt
18
+ # See RFC 4122 for details of UUID at: https://www.ietf.org/rfc/rfc4122.txt
16
19
  def self.uuid_from_hash(hash_class, uuid_namespace, name)
17
20
  if hash_class == Digest::MD5
18
21
  version = 3
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/digest/uuid"
@@ -1,57 +1,55 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerable
2
- # Enumerable#sum was added in Ruby 2.4 but it only works with Numeric elements
4
+ INDEX_WITH_DEFAULT = Object.new
5
+ private_constant :INDEX_WITH_DEFAULT
6
+
7
+ # Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
3
8
  # when we omit an identity.
9
+
10
+ # :stopdoc:
11
+
12
+ # We can't use Refinements here because Refinements with Module which will be prepended
13
+ # doesn't work well https://bugs.ruby-lang.org/issues/13446
14
+ alias :_original_sum_with_required_identity :sum
15
+ private :_original_sum_with_required_identity
16
+
17
+ # :startdoc:
18
+
19
+ # Calculates a sum from the elements.
4
20
  #
5
- # We tried shimming it to attempt the fast native method, rescue TypeError,
6
- # and fall back to the compatible implementation, but that's much slower than
7
- # just calling the compat method in the first place.
8
- if Enumerable.instance_methods(false).include?(:sum) && !((?a..?b).sum rescue false)
9
- # We can't use Refinements here because Refinements with Module which will be prepended
10
- # doesn't work well https://bugs.ruby-lang.org/issues/13446
11
- alias :_original_sum_with_required_identity :sum
12
- private :_original_sum_with_required_identity
13
- # Calculates a sum from the elements.
14
- #
15
- # payments.sum { |p| p.price * p.tax_rate }
16
- # payments.sum(&:price)
17
- #
18
- # The latter is a shortcut for:
19
- #
20
- # payments.inject(0) { |sum, p| sum + p.price }
21
- #
22
- # It can also calculate the sum without the use of a block.
23
- #
24
- # [5, 15, 10].sum # => 30
25
- # ['foo', 'bar'].sum # => "foobar"
26
- # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
27
- #
28
- # The default sum of an empty list is zero. You can override this default:
29
- #
30
- # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
31
- def sum(identity = nil, &block)
32
- if identity
33
- _original_sum_with_required_identity(identity, &block)
34
- elsif block_given?
35
- map(&block).sum(identity)
36
- else
37
- inject(:+) || 0
38
- end
39
- end
40
- else
41
- def sum(identity = nil, &block)
42
- if block_given?
43
- map(&block).sum(identity)
44
- else
45
- sum = identity ? inject(identity, :+) : inject(:+)
46
- sum || identity || 0
47
- end
21
+ # payments.sum { |p| p.price * p.tax_rate }
22
+ # payments.sum(&:price)
23
+ #
24
+ # The latter is a shortcut for:
25
+ #
26
+ # payments.inject(0) { |sum, p| sum + p.price }
27
+ #
28
+ # It can also calculate the sum without the use of a block.
29
+ #
30
+ # [5, 15, 10].sum # => 30
31
+ # ['foo', 'bar'].sum # => "foobar"
32
+ # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
33
+ #
34
+ # The default sum of an empty list is zero. You can override this default:
35
+ #
36
+ # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
37
+ def sum(identity = nil, &block)
38
+ if identity
39
+ _original_sum_with_required_identity(identity, &block)
40
+ elsif block_given?
41
+ map(&block).sum(identity)
42
+ else
43
+ inject(:+) || 0
48
44
  end
49
45
  end
50
46
 
51
- # Convert an enumerable to a hash.
47
+ # Convert an enumerable to a hash, using the block result as the key and the
48
+ # element as the value.
52
49
  #
53
50
  # people.index_by(&:login)
54
51
  # # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
52
+ #
55
53
  # people.index_by { |person| "#{person.first_name} #{person.last_name}" }
56
54
  # # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
57
55
  def index_by
@@ -64,6 +62,33 @@ module Enumerable
64
62
  end
65
63
  end
66
64
 
65
+ # Convert an enumerable to a hash, using the element as the key and the block
66
+ # result as the value.
67
+ #
68
+ # post = Post.new(title: "hey there", body: "what's up?")
69
+ #
70
+ # %i( title body ).index_with { |attr_name| post.public_send(attr_name) }
71
+ # # => { title: "hey there", body: "what's up?" }
72
+ #
73
+ # If an argument is passed instead of a block, it will be used as the value
74
+ # for all elements:
75
+ #
76
+ # %i( created_at updated_at ).index_with(Time.now)
77
+ # # => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 }
78
+ def index_with(default = INDEX_WITH_DEFAULT)
79
+ if block_given?
80
+ result = {}
81
+ each { |elem| result[elem] = yield(elem) }
82
+ result
83
+ elsif default != INDEX_WITH_DEFAULT
84
+ result = {}
85
+ each { |elem| result[elem] = default }
86
+ result
87
+ else
88
+ to_enum(:index_with) { size if respond_to?(:size) }
89
+ end
90
+ end
91
+
67
92
  # Returns +true+ if the enumerable has more than 1 element. Functionally
68
93
  # equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
69
94
  # much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
@@ -80,24 +105,44 @@ module Enumerable
80
105
  end
81
106
  end
82
107
 
108
+ # Returns a new array that includes the passed elements.
109
+ #
110
+ # [ 1, 2, 3 ].including(4, 5)
111
+ # # => [ 1, 2, 3, 4, 5 ]
112
+ #
113
+ # ["David", "Rafael"].including %w[ Aaron Todd ]
114
+ # # => ["David", "Rafael", "Aaron", "Todd"]
115
+ def including(*elements)
116
+ to_a.including(*elements)
117
+ end
118
+
83
119
  # The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
84
120
  # collection does not include the object.
85
121
  def exclude?(object)
86
122
  !include?(object)
87
123
  end
88
124
 
89
- # Returns a copy of the enumerable without the specified elements.
125
+ # Returns a copy of the enumerable excluding the specified elements.
90
126
  #
91
- # ["David", "Rafael", "Aaron", "Todd"].without "Aaron", "Todd"
127
+ # ["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd"
92
128
  # # => ["David", "Rafael"]
93
129
  #
94
- # {foo: 1, bar: 2, baz: 3}.without :bar
130
+ # ["David", "Rafael", "Aaron", "Todd"].excluding %w[ Aaron Todd ]
131
+ # # => ["David", "Rafael"]
132
+ #
133
+ # {foo: 1, bar: 2, baz: 3}.excluding :bar
95
134
  # # => {foo: 1, baz: 3}
96
- def without(*elements)
135
+ def excluding(*elements)
136
+ elements.flatten!(1)
97
137
  reject { |element| elements.include?(element) }
98
138
  end
99
139
 
100
- # Convert an enumerable to an array based on the given key.
140
+ # Alias for #excluding.
141
+ def without(*elements)
142
+ excluding(*elements)
143
+ end
144
+
145
+ # Extract the given key from each element in the enumerable.
101
146
  #
102
147
  # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
103
148
  # # => ["David", "Rafael", "Aaron"]
@@ -108,9 +153,62 @@ module Enumerable
108
153
  if keys.many?
109
154
  map { |element| keys.map { |key| element[key] } }
110
155
  else
111
- map { |element| element[keys.first] }
156
+ key = keys.first
157
+ map { |element| element[key] }
158
+ end
159
+ end
160
+
161
+ # Extract the given key from the first element in the enumerable.
162
+ #
163
+ # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name)
164
+ # # => "David"
165
+ #
166
+ # [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name)
167
+ # # => [1, "David"]
168
+ def pick(*keys)
169
+ return if none?
170
+
171
+ if keys.many?
172
+ keys.map { |key| first[key] }
173
+ else
174
+ first[keys.first]
112
175
  end
113
176
  end
177
+
178
+ # Returns a new +Array+ without the blank items.
179
+ # Uses Object#blank? for determining if an item is blank.
180
+ #
181
+ # [1, "", nil, 2, " ", [], {}, false, true].compact_blank
182
+ # # => [1, 2, true]
183
+ #
184
+ # Set.new([nil, "", 1, 2])
185
+ # # => [2, 1] (or [1, 2])
186
+ #
187
+ # When called on a +Hash+, returns a new +Hash+ without the blank values.
188
+ #
189
+ # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
190
+ # #=> { b: 1, f: true }
191
+ def compact_blank
192
+ reject(&:blank?)
193
+ end
194
+ end
195
+
196
+ class Hash
197
+ # Hash#reject has its own definition, so this needs one too.
198
+ def compact_blank #:nodoc:
199
+ reject { |_k, v| v.blank? }
200
+ end
201
+
202
+ # Removes all blank values from the +Hash+ in place and returns self.
203
+ # Uses Object#blank? for determining if a value is blank.
204
+ #
205
+ # h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
206
+ # h.compact_blank!
207
+ # # => { b: 1, f: true }
208
+ def compact_blank!
209
+ # use delete_if rather than reject! because it always returns self even if nothing changed
210
+ delete_if { |_k, v| v.blank? }
211
+ end
114
212
  end
115
213
 
116
214
  class Range #:nodoc:
@@ -131,27 +229,32 @@ class Range #:nodoc:
131
229
  end
132
230
  end
133
231
 
134
- # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
135
- #
136
- # We tried shimming it to attempt the fast native method, rescue TypeError,
137
- # and fall back to the compatible implementation, but that's much slower than
138
- # just calling the compat method in the first place.
139
- if Array.instance_methods(false).include?(:sum) && !(%w[a].sum rescue false)
140
- # Using Refinements here in order not to expose our internal method
141
- using Module.new {
142
- refine Array do
143
- alias :orig_sum :sum
144
- end
145
- }
232
+ # Using Refinements here in order not to expose our internal method
233
+ using Module.new {
234
+ refine Array do
235
+ alias :orig_sum :sum
236
+ end
237
+ }
146
238
 
147
- class Array
148
- def sum(init = nil, &block) #:nodoc:
149
- if init.is_a?(Numeric) || first.is_a?(Numeric)
150
- init ||= 0
151
- orig_sum(init, &block)
152
- else
153
- super
154
- end
239
+ class Array #:nodoc:
240
+ # Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
241
+ def sum(init = nil, &block)
242
+ if init.is_a?(Numeric) || first.is_a?(Numeric)
243
+ init ||= 0
244
+ orig_sum(init, &block)
245
+ else
246
+ super
155
247
  end
156
248
  end
249
+
250
+ # Removes all blank elements from the +Array+ in place and returns self.
251
+ # Uses Object#blank? for determining if an item is blank.
252
+ #
253
+ # a = [1, "", nil, 2, " ", [], {}, false, true]
254
+ # a.compact_blank!
255
+ # # => [1, 2, true]
256
+ def compact_blank!
257
+ # use delete_if rather than reject! because it always returns self even if nothing changed
258
+ delete_if(&:blank?)
259
+ end
157
260
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "fileutils"
2
4
 
3
5
  class File
@@ -27,7 +29,7 @@ class File
27
29
  old_stat = if exist?(file_name)
28
30
  # Get original file permissions
29
31
  stat(file_name)
30
- elsif temp_dir != dirname(file_name)
32
+ else
31
33
  # If not possible, probe which are the default permissions in the
32
34
  # destination directory.
33
35
  probe_stat_in(dirname(file_name))
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/file/atomic"