activesupport 5.1.1 → 6.1.1
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +360 -442
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +6 -2
- data/lib/active_support/backtrace_cleaner.rb +31 -3
- data/lib/active_support/benchmarkable.rb +3 -1
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache/file_store.rb +37 -36
- data/lib/active_support/cache/mem_cache_store.rb +65 -53
- data/lib/active_support/cache/memory_store.rb +61 -33
- data/lib/active_support/cache/null_store.rb +10 -3
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +68 -22
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/cache.rb +305 -127
- data/lib/active_support/callbacks.rb +106 -98
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -1
- data/lib/active_support/configurable.rb +12 -14
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +7 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +2 -0
- data/lib/active_support/core_ext/array/inquiry.rb +2 -0
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +3 -1
- data/lib/active_support/core_ext/benchmark.rb +4 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +50 -47
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +18 -40
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +2 -0
- data/lib/active_support/core_ext/date/calculations.rb +8 -5
- data/lib/active_support/core_ext/date/conversions.rb +12 -10
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +2 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_time.rb +2 -0
- data/lib/active_support/core_ext/digest/uuid.rb +3 -1
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +174 -71
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +7 -5
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
- data/lib/active_support/core_ext/hash/keys.rb +3 -30
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +2 -1
- data/lib/active_support/core_ext/load_error.rb +3 -8
- data/lib/active_support/core_ext/marshal.rb +4 -0
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
- data/lib/active_support/core_ext/module/concerning.rb +15 -10
- data/lib/active_support/core_ext/module/delegation.rb +103 -58
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +18 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +3 -1
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/numeric.rb +2 -1
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +13 -3
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
- data/lib/active_support/core_ext/object/duplicable.rb +6 -101
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +22 -2
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +7 -2
- data/lib/active_support/core_ext/object/try.rb +19 -7
- data/lib/active_support/core_ext/object/with_options.rb +4 -2
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/regexp.rb +10 -5
- data/lib/active_support/core_ext/securerandom.rb +25 -3
- data/lib/active_support/core_ext/string/access.rb +7 -16
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +3 -0
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +44 -1
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +69 -16
- data/lib/active_support/core_ext/string/inquiry.rb +3 -0
- data/lib/active_support/core_ext/string/multibyte.rb +9 -4
- data/lib/active_support/core_ext/string/output_safety.rb +76 -20
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +73 -18
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +4 -0
- data/lib/active_support/core_ext/time/zones.rb +6 -4
- data/lib/active_support/core_ext/time.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +11 -6
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +135 -60
- data/lib/active_support/deprecation/behaviors.rb +43 -11
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -1
- data/lib/active_support/deprecation/method_wrappers.rb +30 -15
- data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
- data/lib/active_support/deprecation/reporting.rb +54 -9
- data/lib/active_support/deprecation.rb +9 -2
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +6 -6
- data/lib/active_support/duration/iso8601_serializer.rb +20 -14
- data/lib/active_support/duration.rb +179 -41
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +84 -117
- data/lib/active_support/execution_wrapper.rb +3 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +3 -1
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +134 -37
- data/lib/active_support/i18n.rb +4 -1
- data/lib/active_support/i18n_railtie.rb +20 -11
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +19 -8
- data/lib/active_support/inflector/methods.rb +87 -77
- data/lib/active_support/inflector/transliterate.rb +56 -18
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/json/decoding.rb +27 -26
- data/lib/active_support/json/encoding.rb +13 -3
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/key_generator.rb +3 -33
- data/lib/active_support/lazy_load_hooks.rb +33 -10
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +2 -0
- data/lib/active_support/log_subscriber.rb +46 -13
- data/lib/active_support/logger.rb +4 -17
- data/lib/active_support/logger_silence.rb +13 -20
- data/lib/active_support/logger_thread_safe_level.rb +54 -7
- data/lib/active_support/message_encryptor.rb +101 -33
- data/lib/active_support/message_verifier.rb +85 -14
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +12 -68
- data/lib/active_support/multibyte/unicode.rb +17 -327
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +118 -16
- data/lib/active_support/notifications/instrumenter.rb +73 -9
- data/lib/active_support/notifications.rb +74 -8
- data/lib/active_support/number_helper/number_converter.rb +7 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +8 -7
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +16 -53
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +41 -12
- data/lib/active_support/option_merger.rb +24 -3
- data/lib/active_support/ordered_hash.rb +3 -1
- data/lib/active_support/ordered_options.rb +17 -5
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +3 -1
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +3 -10
- data/lib/active_support/railtie.rb +60 -9
- data/lib/active_support/reloader.rb +11 -10
- data/lib/active_support/rescuable.rb +7 -6
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +6 -3
- data/lib/active_support/subscriber.rb +74 -24
- data/lib/active_support/tagged_logging.rb +44 -8
- data/lib/active_support/test_case.rb +94 -2
- data/lib/active_support/testing/assertions.rb +58 -20
- data/lib/active_support/testing/autorun.rb +2 -4
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +2 -1
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +8 -4
- data/lib/active_support/testing/method_call_assertions.rb +30 -1
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +3 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -0
- data/lib/active_support/testing/time_helpers.rb +78 -13
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +113 -41
- data/lib/active_support/values/time_zone.rb +55 -25
- data/lib/active_support/version.rb +2 -0
- data/lib/active_support/xml_mini/jdom.rb +5 -4
- data/lib/active_support/xml_mini/libxml.rb +4 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
- data/lib/active_support/xml_mini/nokogiri.rb +4 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
- data/lib/active_support/xml_mini/rexml.rb +12 -3
- data/lib/active_support/xml_mini.rb +5 -11
- data/lib/active_support.rb +18 -13
- metadata +81 -35
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- 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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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 =
|
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 =
|
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
|
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
|
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
|
247
|
-
|
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
|
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
|
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
|
|
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
|
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/
|
4
|
+
require "active_support/core_ext/module/redefine_method"
|
3
5
|
|
4
6
|
class DateTime
|
5
7
|
include DateAndTime::Compatibility
|
6
8
|
|
7
|
-
|
9
|
+
silence_redefinition_of_method :to_time
|
8
10
|
|
9
|
-
# Either return an instance of
|
10
|
-
# as +self+ or an instance of
|
11
|
-
# in the
|
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 "securerandom"
|
2
4
|
|
3
5
|
module Digest
|
@@ -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:
|
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
|
@@ -1,57 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Enumerable
|
2
|
-
|
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
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
125
|
+
# Returns a copy of the enumerable excluding the specified elements.
|
90
126
|
#
|
91
|
-
# ["David", "Rafael", "Aaron", "Todd"].
|
127
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd"
|
92
128
|
# # => ["David", "Rafael"]
|
93
129
|
#
|
94
|
-
#
|
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
|
135
|
+
def excluding(*elements)
|
136
|
+
elements.flatten!(1)
|
97
137
|
reject { |element| elements.include?(element) }
|
98
138
|
end
|
99
139
|
|
100
|
-
#
|
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
|
-
|
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
|
-
#
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|
-
|
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))
|