activesupport 6.0.4.4 → 7.0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +257 -532
- data/MIT-LICENSE +1 -1
- data/lib/active_support/actionable_error.rb +1 -1
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +5 -5
- data/lib/active_support/benchmarkable.rb +3 -3
- data/lib/active_support/cache/file_store.rb +16 -10
- data/lib/active_support/cache/mem_cache_store.rb +163 -42
- data/lib/active_support/cache/memory_store.rb +57 -29
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +79 -98
- data/lib/active_support/cache/strategy/local_cache.rb +49 -57
- data/lib/active_support/cache.rb +378 -179
- data/lib/active_support/callbacks.rb +230 -122
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +49 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +9 -6
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +13 -12
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +9 -22
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +9 -9
- data/lib/active_support/core_ext/date/conversions.rb +16 -15
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date.rb +1 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +17 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +13 -13
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +39 -13
- data/lib/active_support/core_ext/enumerable.rb +164 -23
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +2 -3
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +2 -2
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +25 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +26 -13
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +40 -36
- data/lib/active_support/core_ext/module/introspection.rb +1 -25
- data/lib/active_support/core_ext/name_error.rb +23 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +80 -73
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +11 -0
- data/lib/active_support/core_ext/object/json.rb +42 -26
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with_options.rb +20 -1
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +6 -25
- data/lib/active_support/core_ext/range/conversions.rb +8 -8
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/securerandom.rb +1 -1
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +3 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +39 -5
- data/lib/active_support/core_ext/string/inquiry.rb +2 -1
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +92 -41
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +25 -7
- data/lib/active_support/core_ext/time/conversions.rb +15 -12
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +7 -22
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +3 -23
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +39 -16
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -769
- data/lib/active_support/deprecation/behaviors.rb +23 -7
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +0 -1
- data/lib/active_support/deprecation/method_wrappers.rb +6 -5
- data/lib/active_support/deprecation/proxy_wrappers.rb +4 -4
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +7 -2
- data/lib/active_support/descendants_tracker.rb +174 -64
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +24 -10
- data/lib/active_support/duration.rb +134 -55
- data/lib/active_support/encrypted_configuration.rb +13 -2
- data/lib/active_support/encrypted_file.rb +32 -3
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +72 -138
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +43 -21
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +51 -25
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +14 -19
- data/lib/active_support/inflector/inflections.rb +24 -9
- data/lib/active_support/inflector/methods.rb +29 -49
- data/lib/active_support/inflector/transliterate.rb +5 -5
- data/lib/active_support/isolated_execution_state.rb +72 -0
- data/lib/active_support/json/decoding.rb +4 -4
- data/lib/active_support/json/encoding.rb +8 -4
- data/lib/active_support/key_generator.rb +23 -6
- data/lib/active_support/lazy_load_hooks.rb +28 -4
- data/lib/active_support/locale/en.yml +8 -4
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +23 -5
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +34 -21
- data/lib/active_support/message_encryptor.rb +16 -13
- data/lib/active_support/message_verifier.rb +50 -18
- data/lib/active_support/messages/metadata.rb +2 -2
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +6 -5
- data/lib/active_support/multibyte/chars.rb +13 -52
- data/lib/active_support/multibyte/unicode.rb +1 -87
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +110 -69
- data/lib/active_support/notifications/instrumenter.rb +37 -29
- data/lib/active_support/notifications.rb +55 -28
- data/lib/active_support/number_helper/number_converter.rb +2 -4
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
- data/lib/active_support/number_helper/rounding_helper.rb +12 -32
- data/lib/active_support/number_helper.rb +29 -16
- data/lib/active_support/option_merger.rb +11 -18
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +9 -3
- data/lib/active_support/parameter_filter.rb +21 -11
- data/lib/active_support/per_thread_registry.rb +6 -1
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +77 -5
- data/lib/active_support/reloader.rb +1 -1
- data/lib/active_support/rescuable.rb +16 -16
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +2 -2
- data/lib/active_support/subscriber.rb +19 -25
- data/lib/active_support/tagged_logging.rb +31 -6
- data/lib/active_support/test_case.rb +13 -21
- data/lib/active_support/testing/assertions.rb +50 -13
- data/lib/active_support/testing/deprecation.rb +52 -1
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +5 -5
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +16 -95
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/stream.rb +3 -5
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +53 -5
- data/lib/active_support/time_with_zone.rb +126 -62
- data/lib/active_support/values/time_zone.rb +54 -23
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +4 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +9 -2
- data/lib/active_support/xml_mini.rb +5 -4
- data/lib/active_support.rb +29 -1
- metadata +46 -45
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
- data/lib/active_support/core_ext/hash/compact.rb +0 -5
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
- data/lib/active_support/core_ext/marshal.rb +0 -24
- data/lib/active_support/core_ext/module/reachable.rb +0 -6
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
- data/lib/active_support/core_ext/range/include_range.rb +0 -9
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -10,6 +10,7 @@ class Date
|
|
10
10
|
short: "%d %b",
|
11
11
|
long: "%B %d, %Y",
|
12
12
|
db: "%Y-%m-%d",
|
13
|
+
inspect: "%Y-%m-%d",
|
13
14
|
number: "%Y%m%d",
|
14
15
|
long_ordinal: lambda { |date|
|
15
16
|
day_format = ActiveSupport::Inflector.ordinalize(date.day)
|
@@ -21,21 +22,21 @@ class Date
|
|
21
22
|
|
22
23
|
# Convert to a formatted string. See DATE_FORMATS for predefined formats.
|
23
24
|
#
|
24
|
-
# This method is aliased to <tt>
|
25
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
25
26
|
#
|
26
27
|
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
27
28
|
#
|
29
|
+
# date.to_fs(:db) # => "2007-11-10"
|
28
30
|
# date.to_formatted_s(:db) # => "2007-11-10"
|
29
|
-
# date.to_s(:db) # => "2007-11-10"
|
30
31
|
#
|
31
|
-
# date.
|
32
|
-
# date.
|
33
|
-
# date.
|
34
|
-
# date.
|
35
|
-
# date.
|
36
|
-
# date.
|
32
|
+
# date.to_fs(:short) # => "10 Nov"
|
33
|
+
# date.to_fs(:number) # => "20071110"
|
34
|
+
# date.to_fs(:long) # => "November 10, 2007"
|
35
|
+
# date.to_fs(:long_ordinal) # => "November 10th, 2007"
|
36
|
+
# date.to_fs(:rfc822) # => "10 Nov 2007"
|
37
|
+
# date.to_fs(:iso8601) # => "2007-11-10"
|
37
38
|
#
|
38
|
-
# == Adding your own date formats to
|
39
|
+
# == Adding your own date formats to to_fs
|
39
40
|
# You can add your own formats to the Date::DATE_FORMATS hash.
|
40
41
|
# Use the format name as the hash key and either a strftime string
|
41
42
|
# or Proc instance that takes a date argument as the value.
|
@@ -43,7 +44,7 @@ class Date
|
|
43
44
|
# # config/initializers/date_formats.rb
|
44
45
|
# Date::DATE_FORMATS[:month_and_year] = '%B %Y'
|
45
46
|
# Date::DATE_FORMATS[:short_ordinal] = ->(date) { date.strftime("%B #{date.day.ordinalize}") }
|
46
|
-
def
|
47
|
+
def to_fs(format = :default)
|
47
48
|
if formatter = DATE_FORMATS[format]
|
48
49
|
if formatter.respond_to?(:call)
|
49
50
|
formatter.call(self).to_s
|
@@ -54,8 +55,8 @@ class Date
|
|
54
55
|
to_default_s
|
55
56
|
end
|
56
57
|
end
|
58
|
+
alias_method :to_formatted_s, :to_fs
|
57
59
|
alias_method :to_default_s, :to_s
|
58
|
-
alias_method :to_s, :to_formatted_s
|
59
60
|
|
60
61
|
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
|
61
62
|
def readable_inspect
|
@@ -67,7 +68,7 @@ class Date
|
|
67
68
|
silence_redefinition_of_method :to_time
|
68
69
|
|
69
70
|
# Converts a Date instance to a Time, where the time is set to the beginning of the day.
|
70
|
-
# The timezone can be either
|
71
|
+
# The timezone can be either +:local+ or +:utc+ (default +:local+).
|
71
72
|
#
|
72
73
|
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
73
74
|
#
|
@@ -76,11 +77,11 @@ class Date
|
|
76
77
|
#
|
77
78
|
# date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
|
78
79
|
#
|
79
|
-
# NOTE: The
|
80
|
-
#
|
80
|
+
# NOTE: The +:local+ timezone is Ruby's *process* timezone, i.e. <tt>ENV['TZ']</tt>.
|
81
|
+
# If the <b>application's</b> timezone is needed, then use +in_time_zone+ instead.
|
81
82
|
def to_time(form = :local)
|
82
83
|
raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
|
83
|
-
::Time.
|
84
|
+
::Time.public_send(form, year, month, day)
|
84
85
|
end
|
85
86
|
|
86
87
|
silence_redefinition_of_method :xmlschema
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
class Date
|
6
|
+
NOT_SET = Object.new # :nodoc:
|
7
|
+
def to_s(format = NOT_SET) # :nodoc:
|
8
|
+
if formatter = DATE_FORMATS[format]
|
9
|
+
ActiveSupport::Deprecation.warn(
|
10
|
+
"Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_fs(#{format.inspect}) instead."
|
11
|
+
)
|
12
|
+
if formatter.respond_to?(:call)
|
13
|
+
formatter.call(self).to_s
|
14
|
+
else
|
15
|
+
strftime(formatter)
|
16
|
+
end
|
17
|
+
elsif format == NOT_SET
|
18
|
+
to_default_s
|
19
|
+
else
|
20
|
+
ActiveSupport::Deprecation.warn(
|
21
|
+
"Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_fs(#{format.inspect}) instead."
|
22
|
+
)
|
23
|
+
to_default_s
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -4,4 +4,5 @@ require "active_support/core_ext/date/acts_like"
|
|
4
4
|
require "active_support/core_ext/date/blank"
|
5
5
|
require "active_support/core_ext/date/calculations"
|
6
6
|
require "active_support/core_ext/date/conversions"
|
7
|
+
require "active_support/core_ext/date/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
|
7
8
|
require "active_support/core_ext/date/zones"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/object/try"
|
4
|
+
require "active_support/core_ext/date_time/conversions"
|
4
5
|
|
5
6
|
module DateAndTime
|
6
7
|
module Calculations
|
@@ -30,6 +31,18 @@ module DateAndTime
|
|
30
31
|
to_date == ::Date.current
|
31
32
|
end
|
32
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
|
+
|
33
46
|
# Returns true if the date/time is in the past.
|
34
47
|
def past?
|
35
48
|
self < self.class.current
|
@@ -188,7 +201,7 @@ module DateAndTime
|
|
188
201
|
end
|
189
202
|
end
|
190
203
|
|
191
|
-
# Short-hand for months_since(3)
|
204
|
+
# Short-hand for <tt>months_since(3)</tt>.
|
192
205
|
def next_quarter
|
193
206
|
months_since(3)
|
194
207
|
end
|
@@ -213,18 +226,18 @@ module DateAndTime
|
|
213
226
|
end
|
214
227
|
alias_method :last_weekday, :prev_weekday
|
215
228
|
|
216
|
-
# Short-hand for months_ago(1)
|
229
|
+
# Short-hand for <tt>months_ago(1)</tt>.
|
217
230
|
def last_month
|
218
231
|
months_ago(1)
|
219
232
|
end
|
220
233
|
|
221
|
-
# Short-hand for months_ago(3)
|
234
|
+
# Short-hand for <tt>months_ago(3)</tt>.
|
222
235
|
def prev_quarter
|
223
236
|
months_ago(3)
|
224
237
|
end
|
225
238
|
alias_method :last_quarter, :prev_quarter
|
226
239
|
|
227
|
-
# Short-hand for years_ago(1)
|
240
|
+
# Short-hand for <tt>years_ago(1)</tt>.
|
228
241
|
def last_year
|
229
242
|
years_ago(1)
|
230
243
|
end
|
@@ -12,5 +12,20 @@ module DateAndTime
|
|
12
12
|
# this behavior, but new apps will have an initializer that sets
|
13
13
|
# this to true, because the new behavior is preferred.
|
14
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 a 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
|
15
30
|
end
|
16
31
|
end
|
@@ -9,21 +9,21 @@ require "active_support/values/time_zone"
|
|
9
9
|
class DateTime
|
10
10
|
# Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
|
11
11
|
#
|
12
|
-
# This method is aliased to <tt>
|
12
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
13
13
|
#
|
14
14
|
# === Examples
|
15
15
|
# datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
|
16
16
|
#
|
17
|
-
# datetime.
|
18
|
-
# datetime.
|
19
|
-
# datetime.
|
20
|
-
# datetime.
|
21
|
-
# datetime.
|
22
|
-
# datetime.
|
23
|
-
# datetime.
|
24
|
-
# datetime.
|
17
|
+
# datetime.to_fs(:db) # => "2007-12-04 00:00:00"
|
18
|
+
# datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
|
19
|
+
# datetime.to_fs(:number) # => "20071204000000"
|
20
|
+
# datetime.to_fs(:short) # => "04 Dec 00:00"
|
21
|
+
# datetime.to_fs(:long) # => "December 04, 2007 00:00"
|
22
|
+
# datetime.to_fs(:long_ordinal) # => "December 4th, 2007 00:00"
|
23
|
+
# datetime.to_fs(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
|
24
|
+
# datetime.to_fs(:iso8601) # => "2007-12-04T00:00:00+00:00"
|
25
25
|
#
|
26
|
-
# == Adding your own datetime formats to
|
26
|
+
# == Adding your own datetime formats to to_fs
|
27
27
|
# DateTime formats are shared with Time. You can add your own to the
|
28
28
|
# Time::DATE_FORMATS hash. Use the format name as the hash key and
|
29
29
|
# either a strftime string or Proc instance that takes a time or
|
@@ -32,15 +32,15 @@ class DateTime
|
|
32
32
|
# # config/initializers/time_formats.rb
|
33
33
|
# Time::DATE_FORMATS[:month_and_year] = '%B %Y'
|
34
34
|
# Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
|
35
|
-
def
|
35
|
+
def to_fs(format = :default)
|
36
36
|
if formatter = ::Time::DATE_FORMATS[format]
|
37
37
|
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
38
38
|
else
|
39
39
|
to_default_s
|
40
40
|
end
|
41
41
|
end
|
42
|
+
alias_method :to_formatted_s, :to_fs
|
42
43
|
alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
|
43
|
-
alias_method :to_s, :to_formatted_s
|
44
44
|
|
45
45
|
# Returns a formatted string of the offset from UTC, or an alternative
|
46
46
|
# string if the time zone is already UTC.
|
@@ -54,7 +54,7 @@ class DateTime
|
|
54
54
|
|
55
55
|
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000".
|
56
56
|
def readable_inspect
|
57
|
-
|
57
|
+
to_fs(:rfc822)
|
58
58
|
end
|
59
59
|
alias_method :default_inspect, :inspect
|
60
60
|
alias_method :inspect, :readable_inspect
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
class DateTime
|
6
|
+
NOT_SET = Object.new # :nodoc:
|
7
|
+
def to_s(format = NOT_SET) # :nodoc:
|
8
|
+
if formatter = ::Time::DATE_FORMATS[format]
|
9
|
+
ActiveSupport::Deprecation.warn(
|
10
|
+
"DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_fs(#{format.inspect}) instead."
|
11
|
+
)
|
12
|
+
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
13
|
+
elsif format == NOT_SET
|
14
|
+
to_default_s
|
15
|
+
else
|
16
|
+
ActiveSupport::Deprecation.warn(
|
17
|
+
"DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_fs(#{format.inspect}) instead."
|
18
|
+
)
|
19
|
+
to_default_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -5,3 +5,4 @@ require "active_support/core_ext/date_time/blank"
|
|
5
5
|
require "active_support/core_ext/date_time/calculations"
|
6
6
|
require "active_support/core_ext/date_time/compatibility"
|
7
7
|
require "active_support/core_ext/date_time/conversions"
|
8
|
+
require "active_support/core_ext/date_time/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
|
@@ -1,29 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "securerandom"
|
4
|
+
require "openssl"
|
4
5
|
|
5
6
|
module Digest
|
6
7
|
module UUID
|
7
|
-
DNS_NAMESPACE = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8"
|
8
|
-
URL_NAMESPACE = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8"
|
9
|
-
OID_NAMESPACE = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8"
|
10
|
-
X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8"
|
8
|
+
DNS_NAMESPACE = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
|
9
|
+
URL_NAMESPACE = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
|
10
|
+
OID_NAMESPACE = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
|
11
|
+
X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" # :nodoc:
|
12
|
+
|
13
|
+
mattr_accessor :use_rfc4122_namespaced_uuids, instance_accessor: false, default: false
|
11
14
|
|
12
15
|
# Generates a v5 non-random UUID (Universally Unique IDentifier).
|
13
16
|
#
|
14
|
-
# Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
|
17
|
+
# Using OpenSSL::Digest::MD5 generates version 3 UUIDs; OpenSSL::Digest::SHA1 generates version 5 UUIDs.
|
15
18
|
# uuid_from_hash always generates the same UUID for a given name and namespace combination.
|
16
19
|
#
|
17
20
|
# See RFC 4122 for details of UUID at: https://www.ietf.org/rfc/rfc4122.txt
|
18
|
-
def self.uuid_from_hash(hash_class,
|
19
|
-
if hash_class == Digest::MD5
|
21
|
+
def self.uuid_from_hash(hash_class, namespace, name)
|
22
|
+
if hash_class == Digest::MD5 || hash_class == OpenSSL::Digest::MD5
|
20
23
|
version = 3
|
21
|
-
elsif hash_class == Digest::SHA1
|
24
|
+
elsif hash_class == Digest::SHA1 || hash_class == OpenSSL::Digest::SHA1
|
22
25
|
version = 5
|
23
26
|
else
|
24
|
-
raise ArgumentError, "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
|
27
|
+
raise ArgumentError, "Expected OpenSSL::Digest::SHA1 or OpenSSL::Digest::MD5, got #{hash_class.name}."
|
25
28
|
end
|
26
29
|
|
30
|
+
uuid_namespace = pack_uuid_namespace(namespace)
|
31
|
+
|
27
32
|
hash = hash_class.new
|
28
33
|
hash.update(uuid_namespace)
|
29
34
|
hash.update(name)
|
@@ -35,19 +40,40 @@ module Digest
|
|
35
40
|
"%08x-%04x-%04x-%04x-%04x%08x" % ary
|
36
41
|
end
|
37
42
|
|
38
|
-
# Convenience method for uuid_from_hash using Digest::MD5.
|
43
|
+
# Convenience method for uuid_from_hash using OpenSSL::Digest::MD5.
|
39
44
|
def self.uuid_v3(uuid_namespace, name)
|
40
|
-
uuid_from_hash(Digest::MD5, uuid_namespace, name)
|
45
|
+
uuid_from_hash(OpenSSL::Digest::MD5, uuid_namespace, name)
|
41
46
|
end
|
42
47
|
|
43
|
-
# Convenience method for uuid_from_hash using Digest::SHA1.
|
48
|
+
# Convenience method for uuid_from_hash using OpenSSL::Digest::SHA1.
|
44
49
|
def self.uuid_v5(uuid_namespace, name)
|
45
|
-
uuid_from_hash(Digest::SHA1, uuid_namespace, name)
|
50
|
+
uuid_from_hash(OpenSSL::Digest::SHA1, uuid_namespace, name)
|
46
51
|
end
|
47
52
|
|
48
53
|
# Convenience method for SecureRandom.uuid.
|
49
54
|
def self.uuid_v4
|
50
55
|
SecureRandom.uuid
|
51
56
|
end
|
57
|
+
|
58
|
+
def self.pack_uuid_namespace(namespace)
|
59
|
+
if [DNS_NAMESPACE, OID_NAMESPACE, URL_NAMESPACE, X500_NAMESPACE].include?(namespace)
|
60
|
+
namespace
|
61
|
+
elsif use_rfc4122_namespaced_uuids == true
|
62
|
+
match_data = namespace.match(/\A(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})\z/)
|
63
|
+
|
64
|
+
raise ArgumentError, "Only UUIDs are valid namespace identifiers" unless match_data.present?
|
65
|
+
|
66
|
+
match_data.captures.map { |s| s.to_i(16) }.pack("NnnnnN")
|
67
|
+
else
|
68
|
+
ActiveSupport::Deprecation.warn <<~WARNING.squish
|
69
|
+
Providing a namespace ID that is not one of the constants defined on Digest::UUID generates an incorrect UUID value according to RFC 4122.
|
70
|
+
To enable the correct behavior, set the Rails.application.config.active_support.use_rfc4122_namespaced_uuids configuration option to true.
|
71
|
+
WARNING
|
72
|
+
|
73
|
+
namespace
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private_class_method :pack_uuid_namespace
|
52
78
|
end
|
53
79
|
end
|
@@ -1,8 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ActiveSupport
|
4
|
+
module EnumerableCoreExt # :nodoc:
|
5
|
+
module Constants
|
6
|
+
private
|
7
|
+
def const_missing(name)
|
8
|
+
if name == :SoleItemExpectedError
|
9
|
+
::ActiveSupport::EnumerableCoreExt::SoleItemExpectedError
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
3
18
|
module Enumerable
|
4
|
-
|
5
|
-
|
19
|
+
# Error generated by +sole+ when called on an enumerable that doesn't have
|
20
|
+
# exactly one item.
|
21
|
+
class SoleItemExpectedError < StandardError; end
|
22
|
+
|
23
|
+
# HACK: For performance reasons, Enumerable shouldn't have any constants of its own.
|
24
|
+
# So we move SoleItemExpectedError into ActiveSupport::EnumerableCoreExt.
|
25
|
+
ActiveSupport::EnumerableCoreExt::SoleItemExpectedError = remove_const(:SoleItemExpectedError)
|
26
|
+
singleton_class.prepend(ActiveSupport::EnumerableCoreExt::Constants)
|
6
27
|
|
7
28
|
# Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
|
8
29
|
# when we omit an identity.
|
@@ -16,6 +37,22 @@ module Enumerable
|
|
16
37
|
|
17
38
|
# :startdoc:
|
18
39
|
|
40
|
+
# Calculates the minimum from the extracted elements.
|
41
|
+
#
|
42
|
+
# payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
|
43
|
+
# payments.minimum(:price) # => 5
|
44
|
+
def minimum(key)
|
45
|
+
map(&key).min
|
46
|
+
end
|
47
|
+
|
48
|
+
# Calculates the maximum from the extracted elements.
|
49
|
+
#
|
50
|
+
# payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
|
51
|
+
# payments.maximum(:price) # => 15
|
52
|
+
def maximum(key)
|
53
|
+
map(&key).max
|
54
|
+
end
|
55
|
+
|
19
56
|
# Calculates a sum from the elements.
|
20
57
|
#
|
21
58
|
# payments.sum { |p| p.price * p.tax_rate }
|
@@ -27,24 +64,36 @@ module Enumerable
|
|
27
64
|
#
|
28
65
|
# It can also calculate the sum without the use of a block.
|
29
66
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
67
|
+
# [5, 15, 10].sum # => 30
|
68
|
+
# ['foo', 'bar'].sum('') # => "foobar"
|
69
|
+
# [[1, 2], [3, 1, 5]].sum([]) # => [1, 2, 3, 1, 5]
|
33
70
|
#
|
34
71
|
# The default sum of an empty list is zero. You can override this default:
|
35
72
|
#
|
36
|
-
#
|
73
|
+
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
|
37
74
|
def sum(identity = nil, &block)
|
38
75
|
if identity
|
39
76
|
_original_sum_with_required_identity(identity, &block)
|
40
77
|
elsif block_given?
|
41
|
-
map(&block).sum
|
78
|
+
map(&block).sum
|
79
|
+
# we check `first(1) == []` to check if we have an
|
80
|
+
# empty Enumerable; checking `empty?` would return
|
81
|
+
# true for `[nil]`, which we want to deprecate to
|
82
|
+
# keep consistent with Ruby
|
83
|
+
elsif first.is_a?(Numeric) || first(1) == []
|
84
|
+
identity ||= 0
|
85
|
+
_original_sum_with_required_identity(identity, &block)
|
42
86
|
else
|
87
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
88
|
+
Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
|
89
|
+
Sum of non-numeric elements requires an initial argument.
|
90
|
+
MSG
|
43
91
|
inject(:+) || 0
|
44
92
|
end
|
45
93
|
end
|
46
94
|
|
47
|
-
# Convert an enumerable to a hash
|
95
|
+
# Convert an enumerable to a hash, using the block result as the key and the
|
96
|
+
# element as the value.
|
48
97
|
#
|
49
98
|
# people.index_by(&:login)
|
50
99
|
# # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
|
@@ -61,23 +110,30 @@ module Enumerable
|
|
61
110
|
end
|
62
111
|
end
|
63
112
|
|
64
|
-
# Convert an enumerable to a hash
|
113
|
+
# Convert an enumerable to a hash, using the element as the key and the block
|
114
|
+
# result as the value.
|
65
115
|
#
|
66
116
|
# post = Post.new(title: "hey there", body: "what's up?")
|
67
117
|
#
|
68
118
|
# %i( title body ).index_with { |attr_name| post.public_send(attr_name) }
|
69
119
|
# # => { title: "hey there", body: "what's up?" }
|
70
|
-
|
120
|
+
#
|
121
|
+
# If an argument is passed instead of a block, it will be used as the value
|
122
|
+
# for all elements:
|
123
|
+
#
|
124
|
+
# %i( created_at updated_at ).index_with(Time.now)
|
125
|
+
# # => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 }
|
126
|
+
def index_with(default = (no_default = true))
|
71
127
|
if block_given?
|
72
128
|
result = {}
|
73
129
|
each { |elem| result[elem] = yield(elem) }
|
74
130
|
result
|
75
|
-
elsif
|
131
|
+
elsif no_default
|
132
|
+
to_enum(:index_with) { size if respond_to?(:size) }
|
133
|
+
else
|
76
134
|
result = {}
|
77
135
|
each { |elem| result[elem] = default }
|
78
136
|
result
|
79
|
-
else
|
80
|
-
to_enum(:index_with) { size if respond_to?(:size) }
|
81
137
|
end
|
82
138
|
end
|
83
139
|
|
@@ -128,13 +184,9 @@ module Enumerable
|
|
128
184
|
elements.flatten!(1)
|
129
185
|
reject { |element| elements.include?(element) }
|
130
186
|
end
|
187
|
+
alias :without :excluding
|
131
188
|
|
132
|
-
#
|
133
|
-
def without(*elements)
|
134
|
-
excluding(*elements)
|
135
|
-
end
|
136
|
-
|
137
|
-
# Convert an enumerable to an array based on the given key.
|
189
|
+
# Extract the given key from each element in the enumerable.
|
138
190
|
#
|
139
191
|
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
|
140
192
|
# # => ["David", "Rafael", "Aaron"]
|
@@ -145,12 +197,91 @@ module Enumerable
|
|
145
197
|
if keys.many?
|
146
198
|
map { |element| keys.map { |key| element[key] } }
|
147
199
|
else
|
148
|
-
|
200
|
+
key = keys.first
|
201
|
+
map { |element| element[key] }
|
149
202
|
end
|
150
203
|
end
|
204
|
+
|
205
|
+
# Extract the given key from the first element in the enumerable.
|
206
|
+
#
|
207
|
+
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name)
|
208
|
+
# # => "David"
|
209
|
+
#
|
210
|
+
# [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name)
|
211
|
+
# # => [1, "David"]
|
212
|
+
def pick(*keys)
|
213
|
+
return if none?
|
214
|
+
|
215
|
+
if keys.many?
|
216
|
+
keys.map { |key| first[key] }
|
217
|
+
else
|
218
|
+
first[keys.first]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Returns a new +Array+ without the blank items.
|
223
|
+
# Uses Object#blank? for determining if an item is blank.
|
224
|
+
#
|
225
|
+
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank
|
226
|
+
# # => [1, 2, true]
|
227
|
+
#
|
228
|
+
# Set.new([nil, "", 1, 2])
|
229
|
+
# # => [2, 1] (or [1, 2])
|
230
|
+
#
|
231
|
+
# When called on a +Hash+, returns a new +Hash+ without the blank values.
|
232
|
+
#
|
233
|
+
# { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
|
234
|
+
# # => { b: 1, f: true }
|
235
|
+
def compact_blank
|
236
|
+
reject(&:blank?)
|
237
|
+
end
|
238
|
+
|
239
|
+
# Returns a new +Array+ where the order has been set to that provided in the +series+, based on the +key+ of the
|
240
|
+
# objects in the original enumerable.
|
241
|
+
#
|
242
|
+
# [ Person.find(5), Person.find(3), Person.find(1) ].in_order_of(:id, [ 1, 5, 3 ])
|
243
|
+
# # => [ Person.find(1), Person.find(5), Person.find(3) ]
|
244
|
+
#
|
245
|
+
# If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
|
246
|
+
# If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result.
|
247
|
+
def in_order_of(key, series)
|
248
|
+
index_by(&key).values_at(*series).compact
|
249
|
+
end
|
250
|
+
|
251
|
+
# Returns the sole item in the enumerable. If there are no items, or more
|
252
|
+
# than one item, raises +Enumerable::SoleItemExpectedError+.
|
253
|
+
#
|
254
|
+
# ["x"].sole # => "x"
|
255
|
+
# Set.new.sole # => Enumerable::SoleItemExpectedError: no item found
|
256
|
+
# { a: 1, b: 2 }.sole # => Enumerable::SoleItemExpectedError: multiple items found
|
257
|
+
def sole
|
258
|
+
case count
|
259
|
+
when 1 then return first # rubocop:disable Style/RedundantReturn
|
260
|
+
when 0 then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "no item found"
|
261
|
+
when 2.. then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "multiple items found"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class Hash
|
267
|
+
# Hash#reject has its own definition, so this needs one too.
|
268
|
+
def compact_blank # :nodoc:
|
269
|
+
reject { |_k, v| v.blank? }
|
270
|
+
end
|
271
|
+
|
272
|
+
# Removes all blank values from the +Hash+ in place and returns self.
|
273
|
+
# Uses Object#blank? for determining if a value is blank.
|
274
|
+
#
|
275
|
+
# h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
|
276
|
+
# h.compact_blank!
|
277
|
+
# # => { b: 1, f: true }
|
278
|
+
def compact_blank!
|
279
|
+
# use delete_if rather than reject! because it always returns self even if nothing changed
|
280
|
+
delete_if { |_k, v| v.blank? }
|
281
|
+
end
|
151
282
|
end
|
152
283
|
|
153
|
-
class Range
|
284
|
+
class Range # :nodoc:
|
154
285
|
# Optimize range sum to use arithmetic progression if a block is not given and
|
155
286
|
# we have a range of numeric values.
|
156
287
|
def sum(identity = nil)
|
@@ -175,8 +306,7 @@ using Module.new {
|
|
175
306
|
end
|
176
307
|
}
|
177
308
|
|
178
|
-
class Array
|
179
|
-
# Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
|
309
|
+
class Array # :nodoc:
|
180
310
|
def sum(init = nil, &block)
|
181
311
|
if init.is_a?(Numeric) || first.is_a?(Numeric)
|
182
312
|
init ||= 0
|
@@ -185,4 +315,15 @@ class Array #:nodoc:
|
|
185
315
|
super
|
186
316
|
end
|
187
317
|
end
|
318
|
+
|
319
|
+
# Removes all blank elements from the +Array+ in place and returns self.
|
320
|
+
# Uses Object#blank? for determining if an item is blank.
|
321
|
+
#
|
322
|
+
# a = [1, "", nil, 2, " ", [], {}, false, true]
|
323
|
+
# a.compact_blank!
|
324
|
+
# # => [1, 2, true]
|
325
|
+
def compact_blank!
|
326
|
+
# use delete_if rather than reject! because it always returns self even if nothing changed
|
327
|
+
delete_if(&:blank?)
|
328
|
+
end
|
188
329
|
end
|
@@ -53,7 +53,7 @@ class File
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# Private utility method.
|
56
|
-
def self.probe_stat_in(dir)
|
56
|
+
def self.probe_stat_in(dir) # :nodoc:
|
57
57
|
basename = [
|
58
58
|
".permissions_check",
|
59
59
|
Thread.current.object_id,
|
@@ -64,6 +64,8 @@ class File
|
|
64
64
|
file_name = join(dir, basename)
|
65
65
|
FileUtils.touch(file_name)
|
66
66
|
stat(file_name)
|
67
|
+
rescue Errno::ENOENT
|
68
|
+
file_name = nil
|
67
69
|
ensure
|
68
70
|
FileUtils.rm_f(file_name) if file_name
|
69
71
|
end
|