activesupport 4.2.11.1 → 6.1.7.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +464 -391
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +34 -6
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +61 -55
- data/lib/active_support/cache/mem_cache_store.rb +115 -100
- data/lib/active_support/cache/memory_store.rb +81 -58
- data/lib/active_support/cache/null_store.rb +11 -7
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +90 -42
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +386 -225
- data/lib/active_support/callbacks.rb +661 -594
- data/lib/active_support/concern.rb +80 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +16 -17
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +41 -1
- data/lib/active_support/core_ext/array/conversions.rb +24 -20
- 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 +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -48
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -25
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +17 -14
- data/lib/active_support/core_ext/date/conversions.rb +27 -24
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +167 -65
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +19 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +8 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +186 -22
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +13 -10
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +20 -43
- 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 +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +10 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +63 -69
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +148 -0
- data/lib/active_support/core_ext/module/concerning.rb +19 -14
- data/lib/active_support/core_ext/module/delegation.rb +164 -51
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +23 -22
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -11
- data/lib/active_support/core_ext/name_error.rb +51 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +133 -136
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +5 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -3
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +13 -93
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +63 -21
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +81 -23
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/each.rb +18 -17
- 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 +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +8 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +48 -6
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +102 -26
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +125 -40
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- 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 +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +137 -53
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +22 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +11 -8
- 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 +210 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
- data/lib/active_support/dependencies.rb +241 -175
- data/lib/active_support/deprecation/behaviors.rb +58 -12
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +59 -0
- data/lib/active_support/duration.rb +364 -39
- 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 +170 -0
- data/lib/active_support/execution_wrapper.rb +132 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +7 -5
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +171 -48
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +47 -16
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +58 -14
- data/lib/active_support/inflector/methods.rb +186 -169
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +32 -30
- data/lib/active_support/json/encoding.rb +22 -61
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +11 -43
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +9 -3
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +52 -19
- data/lib/active_support/logger.rb +10 -24
- data/lib/active_support/logger_silence.rb +14 -20
- data/lib/active_support/logger_thread_safe_level.rb +56 -10
- data/lib/active_support/message_encryptor.rb +167 -57
- data/lib/active_support/message_verifier.rb +151 -18
- 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 +35 -80
- data/lib/active_support/multibyte/unicode.rb +22 -330
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +125 -23
- data/lib/active_support/notifications/instrumenter.rb +98 -16
- data/lib/active_support/notifications.rb +82 -14
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -14
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
- data/lib/active_support/number_helper/number_to_human_converter.rb +14 -11
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +12 -10
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +29 -57
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +123 -71
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +7 -5
- data/lib/active_support/ordered_options.rb +35 -7
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +10 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +66 -10
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- 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 +13 -4
- data/lib/active_support/subscriber.rb +80 -31
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +107 -44
- data/lib/active_support/testing/assertions.rb +158 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +13 -10
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +35 -26
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- 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 +13 -8
- data/lib/active_support/testing/stream.rb +43 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +121 -20
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +215 -51
- data/lib/active_support/values/time_zone.rb +223 -71
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -115
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +18 -9
- data/lib/active_support/xml_mini.rb +38 -46
- data/lib/active_support.rb +25 -11
- metadata +100 -43
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/hash/compact.rb +0 -24
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -23
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,4 +1,6 @@
|
|
1
|
-
|
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
|
-
#
|
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
|
@@ -43,13 +49,23 @@ class DateTime
|
|
43
49
|
# DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => DateTime.new(1981, 8, 1, 22, 35, 0)
|
44
50
|
# DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
|
45
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
|
+
|
46
62
|
::DateTime.civil(
|
47
63
|
options.fetch(:year, year),
|
48
64
|
options.fetch(:month, month),
|
49
65
|
options.fetch(:day, day),
|
50
66
|
options.fetch(:hour, hour),
|
51
67
|
options.fetch(:min, options[:hour] ? 0 : min),
|
52
|
-
options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec +
|
68
|
+
options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
|
53
69
|
options.fetch(:offset, offset),
|
54
70
|
options.fetch(:start, start)
|
55
71
|
)
|
@@ -71,7 +87,7 @@ class DateTime
|
|
71
87
|
end
|
72
88
|
|
73
89
|
d = to_date.advance(options)
|
74
|
-
datetime_advanced_by_date = change(:
|
90
|
+
datetime_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
|
75
91
|
seconds_to_advance = \
|
76
92
|
options.fetch(:seconds, 0) +
|
77
93
|
options.fetch(:minutes, 0) * 60 +
|
@@ -94,13 +110,13 @@ class DateTime
|
|
94
110
|
# instance time. Do not use this method in combination with x.months, use
|
95
111
|
# months_since instead!
|
96
112
|
def since(seconds)
|
97
|
-
self + Rational(seconds
|
113
|
+
self + Rational(seconds, 86400)
|
98
114
|
end
|
99
115
|
alias :in :since
|
100
116
|
|
101
117
|
# Returns a new DateTime representing the start of the day (0:00).
|
102
118
|
def beginning_of_day
|
103
|
-
change(:
|
119
|
+
change(hour: 0)
|
104
120
|
end
|
105
121
|
alias :midnight :beginning_of_day
|
106
122
|
alias :at_midnight :beginning_of_day
|
@@ -108,7 +124,7 @@ class DateTime
|
|
108
124
|
|
109
125
|
# Returns a new DateTime representing the middle of the day (12:00)
|
110
126
|
def middle_of_day
|
111
|
-
change(:
|
127
|
+
change(hour: 12)
|
112
128
|
end
|
113
129
|
alias :midday :middle_of_day
|
114
130
|
alias :noon :middle_of_day
|
@@ -118,31 +134,31 @@ class DateTime
|
|
118
134
|
|
119
135
|
# Returns a new DateTime representing the end of the day (23:59:59).
|
120
136
|
def end_of_day
|
121
|
-
change(:
|
137
|
+
change(hour: 23, min: 59, sec: 59, usec: Rational(999999999, 1000))
|
122
138
|
end
|
123
139
|
alias :at_end_of_day :end_of_day
|
124
140
|
|
125
141
|
# Returns a new DateTime representing the start of the hour (hh:00:00).
|
126
142
|
def beginning_of_hour
|
127
|
-
change(:
|
143
|
+
change(min: 0)
|
128
144
|
end
|
129
145
|
alias :at_beginning_of_hour :beginning_of_hour
|
130
146
|
|
131
147
|
# Returns a new DateTime representing the end of the hour (hh:59:59).
|
132
148
|
def end_of_hour
|
133
|
-
change(:
|
149
|
+
change(min: 59, sec: 59, usec: Rational(999999999, 1000))
|
134
150
|
end
|
135
151
|
alias :at_end_of_hour :end_of_hour
|
136
152
|
|
137
153
|
# Returns a new DateTime representing the start of the minute (hh:mm:00).
|
138
154
|
def beginning_of_minute
|
139
|
-
change(:
|
155
|
+
change(sec: 0)
|
140
156
|
end
|
141
157
|
alias :at_beginning_of_minute :beginning_of_minute
|
142
158
|
|
143
159
|
# Returns a new DateTime representing the end of the minute (hh:mm:59).
|
144
160
|
def end_of_minute
|
145
|
-
change(:
|
161
|
+
change(sec: 59, usec: Rational(999999999, 1000))
|
146
162
|
end
|
147
163
|
alias :at_end_of_minute :end_of_minute
|
148
164
|
|
@@ -157,12 +173,17 @@ class DateTime
|
|
157
173
|
end
|
158
174
|
alias_method :getlocal, :localtime
|
159
175
|
|
160
|
-
# Returns a <tt>
|
176
|
+
# Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
|
161
177
|
#
|
162
178
|
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
|
163
179
|
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
|
164
180
|
def utc
|
165
|
-
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
|
+
)
|
166
187
|
end
|
167
188
|
alias_method :getgm, :utc
|
168
189
|
alias_method :getutc, :utc
|
@@ -181,13 +202,10 @@ class DateTime
|
|
181
202
|
# Layers additional behavior on DateTime#<=> so that Time and
|
182
203
|
# ActiveSupport::TimeWithZone instances can be compared with a DateTime.
|
183
204
|
def <=>(other)
|
184
|
-
if other.
|
185
|
-
super
|
186
|
-
elsif other.respond_to? :to_datetime
|
205
|
+
if other.respond_to? :to_datetime
|
187
206
|
super other.to_datetime rescue nil
|
188
207
|
else
|
189
|
-
|
208
|
+
super
|
190
209
|
end
|
191
210
|
end
|
192
|
-
|
193
211
|
end
|
@@ -1,14 +1,16 @@
|
|
1
|
-
|
2
|
-
|
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"
|
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,8 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
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
|
@@ -92,12 +96,11 @@ class DateTime
|
|
92
96
|
end
|
93
97
|
|
94
98
|
private
|
99
|
+
def offset_in_seconds
|
100
|
+
(offset * 86400).to_i
|
101
|
+
end
|
95
102
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
def seconds_since_unix_epoch
|
101
|
-
(jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
|
102
|
-
end
|
103
|
+
def seconds_since_unix_epoch
|
104
|
+
(jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
|
105
|
+
end
|
103
106
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/date_time/acts_like"
|
4
|
+
require "active_support/core_ext/date_time/blank"
|
5
|
+
require "active_support/core_ext/date_time/calculations"
|
6
|
+
require "active_support/core_ext/date_time/compatibility"
|
7
|
+
require "active_support/core_ext/date_time/conversions"
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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:
|
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
|
@@ -26,7 +29,7 @@ module Digest
|
|
26
29
|
hash.update(uuid_namespace)
|
27
30
|
hash.update(name)
|
28
31
|
|
29
|
-
ary = hash.digest.unpack(
|
32
|
+
ary = hash.digest.unpack("NnnnnN")
|
30
33
|
ary[2] = (ary[2] & 0x0FFF) | (version << 12)
|
31
34
|
ary[3] = (ary[3] & 0x3FFF) | 0x8000
|
32
35
|
|
@@ -35,12 +38,12 @@ module Digest
|
|
35
38
|
|
36
39
|
# Convenience method for uuid_from_hash using Digest::MD5.
|
37
40
|
def self.uuid_v3(uuid_namespace, name)
|
38
|
-
|
41
|
+
uuid_from_hash(Digest::MD5, uuid_namespace, name)
|
39
42
|
end
|
40
43
|
|
41
44
|
# Convenience method for uuid_from_hash using Digest::SHA1.
|
42
45
|
def self.uuid_v5(uuid_namespace, name)
|
43
|
-
|
46
|
+
uuid_from_hash(Digest::SHA1, uuid_namespace, name)
|
44
47
|
end
|
45
48
|
|
46
49
|
# Convenience method for SecureRandom.uuid.
|
@@ -1,4 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Enumerable
|
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
|
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
|
+
|
2
19
|
# Calculates a sum from the elements.
|
3
20
|
#
|
4
21
|
# payments.sum { |p| p.price * p.tax_rate }
|
@@ -12,33 +29,66 @@ module Enumerable
|
|
12
29
|
#
|
13
30
|
# [5, 15, 10].sum # => 30
|
14
31
|
# ['foo', 'bar'].sum # => "foobar"
|
15
|
-
# [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
|
32
|
+
# [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
|
16
33
|
#
|
17
34
|
# The default sum of an empty list is zero. You can override this default:
|
18
35
|
#
|
19
36
|
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
|
20
|
-
def sum(identity =
|
21
|
-
if
|
37
|
+
def sum(identity = nil, &block)
|
38
|
+
if identity
|
39
|
+
_original_sum_with_required_identity(identity, &block)
|
40
|
+
elsif block_given?
|
22
41
|
map(&block).sum(identity)
|
23
42
|
else
|
24
|
-
inject
|
43
|
+
inject(:+) || 0
|
25
44
|
end
|
26
45
|
end
|
27
46
|
|
28
|
-
# 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.
|
29
49
|
#
|
30
50
|
# people.index_by(&:login)
|
31
|
-
#
|
51
|
+
# # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
|
52
|
+
#
|
32
53
|
# people.index_by { |person| "#{person.first_name} #{person.last_name}" }
|
33
|
-
#
|
54
|
+
# # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
|
34
55
|
def index_by
|
35
56
|
if block_given?
|
36
|
-
|
57
|
+
result = {}
|
58
|
+
each { |elem| result[yield(elem)] = elem }
|
59
|
+
result
|
37
60
|
else
|
38
61
|
to_enum(:index_by) { size if respond_to?(:size) }
|
39
62
|
end
|
40
63
|
end
|
41
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
|
+
|
42
92
|
# Returns +true+ if the enumerable has more than 1 element. Functionally
|
43
93
|
# equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
|
44
94
|
# much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
|
@@ -55,42 +105,156 @@ module Enumerable
|
|
55
105
|
end
|
56
106
|
end
|
57
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
|
+
|
58
119
|
# The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
|
59
120
|
# collection does not include the object.
|
60
121
|
def exclude?(object)
|
61
122
|
!include?(object)
|
62
123
|
end
|
124
|
+
|
125
|
+
# Returns a copy of the enumerable excluding the specified elements.
|
126
|
+
#
|
127
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd"
|
128
|
+
# # => ["David", "Rafael"]
|
129
|
+
#
|
130
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding %w[ Aaron Todd ]
|
131
|
+
# # => ["David", "Rafael"]
|
132
|
+
#
|
133
|
+
# {foo: 1, bar: 2, baz: 3}.excluding :bar
|
134
|
+
# # => {foo: 1, baz: 3}
|
135
|
+
def excluding(*elements)
|
136
|
+
elements.flatten!(1)
|
137
|
+
reject { |element| elements.include?(element) }
|
138
|
+
end
|
139
|
+
|
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.
|
146
|
+
#
|
147
|
+
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
|
148
|
+
# # => ["David", "Rafael", "Aaron"]
|
149
|
+
#
|
150
|
+
# [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)
|
151
|
+
# # => [[1, "David"], [2, "Rafael"]]
|
152
|
+
def pluck(*keys)
|
153
|
+
if keys.many?
|
154
|
+
map { |element| keys.map { |key| element[key] } }
|
155
|
+
else
|
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]
|
175
|
+
end
|
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
|
63
212
|
end
|
64
213
|
|
65
214
|
class Range #:nodoc:
|
66
215
|
# Optimize range sum to use arithmetic progression if a block is not given and
|
67
216
|
# we have a range of numeric values.
|
68
|
-
def sum(identity =
|
217
|
+
def sum(identity = nil)
|
69
218
|
if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
|
70
219
|
super
|
71
220
|
else
|
72
221
|
actual_last = exclude_end? ? (last - 1) : last
|
73
222
|
if actual_last >= first
|
74
|
-
|
223
|
+
sum = identity || 0
|
224
|
+
sum + (actual_last - first + 1) * (actual_last + first) / 2
|
75
225
|
else
|
76
|
-
identity
|
226
|
+
identity || 0
|
77
227
|
end
|
78
228
|
end
|
79
229
|
end
|
80
230
|
end
|
81
231
|
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
+
}
|
238
|
+
|
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
|
93
246
|
super
|
94
247
|
end
|
95
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
|
96
260
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
2
4
|
|
3
5
|
class File
|
4
6
|
# Write to a file atomically. Useful for situations where you don't
|
@@ -8,51 +10,56 @@ class File
|
|
8
10
|
# file.write('hello')
|
9
11
|
# end
|
10
12
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
+
# This method needs to create a temporary file. By default it will create it
|
14
|
+
# in the same directory as the destination file. If you don't like this
|
15
|
+
# behavior you can provide a different directory but it must be on the
|
16
|
+
# same physical filesystem as the file you're trying to write.
|
13
17
|
#
|
14
18
|
# File.atomic_write('/data/something.important', '/data/tmp') do |file|
|
15
19
|
# file.write('hello')
|
16
20
|
# end
|
17
|
-
def self.atomic_write(file_name, temp_dir =
|
18
|
-
require
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
21
|
+
def self.atomic_write(file_name, temp_dir = dirname(file_name))
|
22
|
+
require "tempfile" unless defined?(Tempfile)
|
23
|
+
|
24
|
+
Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file|
|
25
|
+
temp_file.binmode
|
26
|
+
return_val = yield temp_file
|
27
|
+
temp_file.close
|
28
|
+
|
29
|
+
old_stat = if exist?(file_name)
|
30
|
+
# Get original file permissions
|
31
|
+
stat(file_name)
|
32
|
+
else
|
33
|
+
# If not possible, probe which are the default permissions in the
|
34
|
+
# destination directory.
|
35
|
+
probe_stat_in(dirname(file_name))
|
36
|
+
end
|
34
37
|
|
35
|
-
|
36
|
-
|
38
|
+
if old_stat
|
39
|
+
# Set correct permissions on new file
|
40
|
+
begin
|
41
|
+
chown(old_stat.uid, old_stat.gid, temp_file.path)
|
42
|
+
# This operation will affect filesystem ACL's
|
43
|
+
chmod(old_stat.mode, temp_file.path)
|
44
|
+
rescue Errno::EPERM, Errno::EACCES
|
45
|
+
# Changing file ownership failed, moving on.
|
46
|
+
end
|
47
|
+
end
|
37
48
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
# This operation will affect filesystem ACL's
|
42
|
-
chmod(old_stat.mode, file_name)
|
43
|
-
rescue Errno::EPERM, Errno::EACCES
|
44
|
-
# Changing file ownership failed, moving on.
|
49
|
+
# Overwrite original file with temp file
|
50
|
+
rename(temp_file.path, file_name)
|
51
|
+
return_val
|
45
52
|
end
|
46
53
|
end
|
47
54
|
|
48
55
|
# Private utility method.
|
49
56
|
def self.probe_stat_in(dir) #:nodoc:
|
50
57
|
basename = [
|
51
|
-
|
58
|
+
".permissions_check",
|
52
59
|
Thread.current.object_id,
|
53
60
|
Process.pid,
|
54
61
|
rand(1000000)
|
55
|
-
].join(
|
62
|
+
].join(".")
|
56
63
|
|
57
64
|
file_name = join(dir, basename)
|
58
65
|
FileUtils.touch(file_name)
|