activesupport 6.0.6 → 7.0.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 +4 -4
- data/CHANGELOG.md +224 -608
- 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 +3 -3
- 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 +143 -38
- data/lib/active_support/cache/memory_store.rb +56 -28
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +62 -87
- data/lib/active_support/cache/strategy/local_cache.rb +46 -57
- data/lib/active_support/cache.rb +268 -77
- data/lib/active_support/callbacks.rb +226 -118
- 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 +9 -7
- 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.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 +11 -24
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +4 -4
- data/lib/active_support/core_ext/date/conversions.rb +5 -4
- 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 +13 -0
- 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 +5 -5
- 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 +139 -15
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash/conversions.rb +2 -2
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
- 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/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 +79 -72
- 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 +41 -25
- 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.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- 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 +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +62 -67
- 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 +23 -5
- data/lib/active_support/core_ext/time/conversions.rb +6 -3
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +4 -19
- 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 +19 -3
- 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 +3 -3
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- 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 +11 -1
- data/lib/active_support/encrypted_file.rb +20 -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 +70 -134
- 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 +41 -18
- 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 +2 -2
- 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 +4 -4
- data/lib/active_support/isolated_execution_state.rb +56 -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 +19 -2
- data/lib/active_support/locale/en.yml +8 -4
- data/lib/active_support/log_subscriber.rb +21 -3
- 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 +12 -10
- 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 +47 -26
- 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 +9 -16
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +8 -2
- 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 +6 -6
- 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 +9 -21
- data/lib/active_support/testing/assertions.rb +49 -12
- 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 +120 -55
- data/lib/active_support/values/time_zone.rb +49 -18
- 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 +45 -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
@@ -44,7 +44,7 @@ class String
|
|
44
44
|
# str.from(0).to(-1) # => "hello"
|
45
45
|
# str.from(1).to(-2) # => "ell"
|
46
46
|
def from(position)
|
47
|
-
self[position
|
47
|
+
self[position, length]
|
48
48
|
end
|
49
49
|
|
50
50
|
# Returns a substring from the beginning of the string to the given position.
|
@@ -61,7 +61,8 @@ class String
|
|
61
61
|
# str.from(0).to(-1) # => "hello"
|
62
62
|
# str.from(1).to(-2) # => "ell"
|
63
63
|
def to(position)
|
64
|
-
|
64
|
+
position += size if position < 0
|
65
|
+
self[0, position + 1] || +""
|
65
66
|
end
|
66
67
|
|
67
68
|
# Returns the first character. If a limit is supplied, returns a substring
|
@@ -75,17 +76,7 @@ class String
|
|
75
76
|
# str.first(0) # => ""
|
76
77
|
# str.first(6) # => "hello"
|
77
78
|
def first(limit = 1)
|
78
|
-
|
79
|
-
"Calling String#first with a negative integer limit " \
|
80
|
-
"will raise an ArgumentError in Rails 6.1."
|
81
|
-
) if limit < 0
|
82
|
-
if limit == 0
|
83
|
-
""
|
84
|
-
elsif limit >= size
|
85
|
-
dup
|
86
|
-
else
|
87
|
-
to(limit - 1)
|
88
|
-
end
|
79
|
+
self[0, limit] || raise(ArgumentError, "negative limit")
|
89
80
|
end
|
90
81
|
|
91
82
|
# Returns the last character of the string. If a limit is supplied, returns a substring
|
@@ -99,16 +90,6 @@ class String
|
|
99
90
|
# str.last(0) # => ""
|
100
91
|
# str.last(6) # => "hello"
|
101
92
|
def last(limit = 1)
|
102
|
-
|
103
|
-
"Calling String#last with a negative integer limit " \
|
104
|
-
"will raise an ArgumentError in Rails 6.1."
|
105
|
-
) if limit < 0
|
106
|
-
if limit == 0
|
107
|
-
""
|
108
|
-
elsif limit >= size
|
109
|
-
dup
|
110
|
-
else
|
111
|
-
from(-limit)
|
112
|
-
end
|
93
|
+
self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
|
113
94
|
end
|
114
95
|
end
|
@@ -18,6 +18,7 @@ class String
|
|
18
18
|
# "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
|
19
19
|
# "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
|
20
20
|
# "12/13/2012".to_time # => ArgumentError: argument out of range
|
21
|
+
# "1604326192".to_time # => ArgumentError: argument out of range
|
21
22
|
def to_time(form = :local)
|
22
23
|
parts = Date._parse(self, false)
|
23
24
|
used_keys = %i(year mon mday hour min sec sec_fraction offset)
|
@@ -30,6 +30,8 @@ class String
|
|
30
30
|
# 'apple'.pluralize(2) # => "apples"
|
31
31
|
# 'ley'.pluralize(:es) # => "leyes"
|
32
32
|
# 'ley'.pluralize(1, :es) # => "ley"
|
33
|
+
#
|
34
|
+
# See ActiveSupport::Inflector.pluralize.
|
33
35
|
def pluralize(count = nil, locale = :en)
|
34
36
|
locale = count if count.is_a?(Symbol)
|
35
37
|
if count == 1
|
@@ -53,28 +55,34 @@ class String
|
|
53
55
|
# 'the blue mailmen'.singularize # => "the blue mailman"
|
54
56
|
# 'CamelOctopi'.singularize # => "CamelOctopus"
|
55
57
|
# 'leyes'.singularize(:es) # => "ley"
|
58
|
+
#
|
59
|
+
# See ActiveSupport::Inflector.singularize.
|
56
60
|
def singularize(locale = :en)
|
57
61
|
ActiveSupport::Inflector.singularize(self, locale)
|
58
62
|
end
|
59
63
|
|
60
64
|
# +constantize+ tries to find a declared constant with the name specified
|
61
65
|
# in the string. It raises a NameError when the name is not in CamelCase
|
62
|
-
# or is not initialized.
|
66
|
+
# or is not initialized.
|
63
67
|
#
|
64
68
|
# 'Module'.constantize # => Module
|
65
69
|
# 'Class'.constantize # => Class
|
66
70
|
# 'blargle'.constantize # => NameError: wrong constant name blargle
|
71
|
+
#
|
72
|
+
# See ActiveSupport::Inflector.constantize.
|
67
73
|
def constantize
|
68
74
|
ActiveSupport::Inflector.constantize(self)
|
69
75
|
end
|
70
76
|
|
71
77
|
# +safe_constantize+ tries to find a declared constant with the name specified
|
72
78
|
# in the string. It returns +nil+ when the name is not in CamelCase
|
73
|
-
# or is not initialized.
|
79
|
+
# or is not initialized.
|
74
80
|
#
|
75
81
|
# 'Module'.safe_constantize # => Module
|
76
82
|
# 'Class'.safe_constantize # => Class
|
77
83
|
# 'blargle'.safe_constantize # => nil
|
84
|
+
#
|
85
|
+
# See ActiveSupport::Inflector.safe_constantize.
|
78
86
|
def safe_constantize
|
79
87
|
ActiveSupport::Inflector.safe_constantize(self)
|
80
88
|
end
|
@@ -88,6 +96,10 @@ class String
|
|
88
96
|
# 'active_record'.camelize(:lower) # => "activeRecord"
|
89
97
|
# 'active_record/errors'.camelize # => "ActiveRecord::Errors"
|
90
98
|
# 'active_record/errors'.camelize(:lower) # => "activeRecord::Errors"
|
99
|
+
#
|
100
|
+
# +camelize+ is also aliased as +camelcase+.
|
101
|
+
#
|
102
|
+
# See ActiveSupport::Inflector.camelize.
|
91
103
|
def camelize(first_letter = :upper)
|
92
104
|
case first_letter
|
93
105
|
when :upper
|
@@ -108,11 +120,13 @@ class String
|
|
108
120
|
# optional parameter +keep_id_suffix+ to true.
|
109
121
|
# By default, this parameter is false.
|
110
122
|
#
|
111
|
-
# +titleize+ is also aliased as +titlecase+.
|
112
|
-
#
|
113
123
|
# 'man from the boondocks'.titleize # => "Man From The Boondocks"
|
114
124
|
# 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
|
115
125
|
# 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
|
126
|
+
#
|
127
|
+
# +titleize+ is also aliased as +titlecase+.
|
128
|
+
#
|
129
|
+
# See ActiveSupport::Inflector.titleize.
|
116
130
|
def titleize(keep_id_suffix: false)
|
117
131
|
ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
|
118
132
|
end
|
@@ -124,6 +138,8 @@ class String
|
|
124
138
|
#
|
125
139
|
# 'ActiveModel'.underscore # => "active_model"
|
126
140
|
# 'ActiveModel::Errors'.underscore # => "active_model/errors"
|
141
|
+
#
|
142
|
+
# See ActiveSupport::Inflector.underscore.
|
127
143
|
def underscore
|
128
144
|
ActiveSupport::Inflector.underscore(self)
|
129
145
|
end
|
@@ -131,6 +147,8 @@ class String
|
|
131
147
|
# Replaces underscores with dashes in the string.
|
132
148
|
#
|
133
149
|
# 'puni_puni'.dasherize # => "puni-puni"
|
150
|
+
#
|
151
|
+
# See ActiveSupport::Inflector.dasherize.
|
134
152
|
def dasherize
|
135
153
|
ActiveSupport::Inflector.dasherize(self)
|
136
154
|
end
|
@@ -142,6 +160,8 @@ class String
|
|
142
160
|
# '::Inflections'.demodulize # => "Inflections"
|
143
161
|
# ''.demodulize # => ''
|
144
162
|
#
|
163
|
+
# See ActiveSupport::Inflector.demodulize.
|
164
|
+
#
|
145
165
|
# See also +deconstantize+.
|
146
166
|
def demodulize
|
147
167
|
ActiveSupport::Inflector.demodulize(self)
|
@@ -155,6 +175,8 @@ class String
|
|
155
175
|
# '::String'.deconstantize # => ""
|
156
176
|
# ''.deconstantize # => ""
|
157
177
|
#
|
178
|
+
# See ActiveSupport::Inflector.deconstantize.
|
179
|
+
#
|
158
180
|
# See also +demodulize+.
|
159
181
|
def deconstantize
|
160
182
|
ActiveSupport::Inflector.deconstantize(self)
|
@@ -192,6 +214,8 @@ class String
|
|
192
214
|
#
|
193
215
|
# <%= link_to(@person.name, person_path) %>
|
194
216
|
# # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
|
217
|
+
#
|
218
|
+
# See ActiveSupport::Inflector.parameterize.
|
195
219
|
def parameterize(separator: "-", preserve_case: false, locale: nil)
|
196
220
|
ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case, locale: locale)
|
197
221
|
end
|
@@ -202,6 +226,8 @@ class String
|
|
202
226
|
# 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
|
203
227
|
# 'ham_and_egg'.tableize # => "ham_and_eggs"
|
204
228
|
# 'fancyCategory'.tableize # => "fancy_categories"
|
229
|
+
#
|
230
|
+
# See ActiveSupport::Inflector.tableize.
|
205
231
|
def tableize
|
206
232
|
ActiveSupport::Inflector.tableize(self)
|
207
233
|
end
|
@@ -212,6 +238,8 @@ class String
|
|
212
238
|
#
|
213
239
|
# 'ham_and_eggs'.classify # => "HamAndEgg"
|
214
240
|
# 'posts'.classify # => "Post"
|
241
|
+
#
|
242
|
+
# See ActiveSupport::Inflector.classify.
|
215
243
|
def classify
|
216
244
|
ActiveSupport::Inflector.classify(self)
|
217
245
|
end
|
@@ -232,7 +260,9 @@ class String
|
|
232
260
|
# 'author_id'.humanize # => "Author"
|
233
261
|
# 'author_id'.humanize(capitalize: false) # => "author"
|
234
262
|
# '_id'.humanize # => "Id"
|
235
|
-
# 'author_id'.humanize(keep_id_suffix: true) # => "Author
|
263
|
+
# 'author_id'.humanize(keep_id_suffix: true) # => "Author id"
|
264
|
+
#
|
265
|
+
# See ActiveSupport::Inflector.humanize.
|
236
266
|
def humanize(capitalize: true, keep_id_suffix: false)
|
237
267
|
ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
|
238
268
|
end
|
@@ -242,6 +272,8 @@ class String
|
|
242
272
|
# 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
|
243
273
|
# 'w'.upcase_first # => "W"
|
244
274
|
# ''.upcase_first # => ""
|
275
|
+
#
|
276
|
+
# See ActiveSupport::Inflector.upcase_first.
|
245
277
|
def upcase_first
|
246
278
|
ActiveSupport::Inflector.upcase_first(self)
|
247
279
|
end
|
@@ -253,6 +285,8 @@ class String
|
|
253
285
|
# 'Message'.foreign_key # => "message_id"
|
254
286
|
# 'Message'.foreign_key(false) # => "messageid"
|
255
287
|
# 'Admin::Post'.foreign_key # => "post_id"
|
288
|
+
#
|
289
|
+
# See ActiveSupport::Inflector.foreign_key.
|
256
290
|
def foreign_key(separate_class_name_and_id_with_underscore = true)
|
257
291
|
ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
|
258
292
|
end
|
@@ -47,9 +47,9 @@ class String
|
|
47
47
|
# iso_str.is_utf8? # => false
|
48
48
|
def is_utf8?
|
49
49
|
case encoding
|
50
|
-
when Encoding::UTF_8
|
50
|
+
when Encoding::UTF_8, Encoding::US_ASCII
|
51
51
|
valid_encoding?
|
52
|
-
when Encoding::ASCII_8BIT
|
52
|
+
when Encoding::ASCII_8BIT
|
53
53
|
dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
54
54
|
else
|
55
55
|
false
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "erb"
|
4
|
-
require "active_support/core_ext/kernel/singleton_class"
|
5
4
|
require "active_support/core_ext/module/redefine_method"
|
6
5
|
require "active_support/multibyte/unicode"
|
7
6
|
|
@@ -12,14 +11,6 @@ class ERB
|
|
12
11
|
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
|
13
12
|
JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
|
14
13
|
|
15
|
-
# Following XML requirements: https://www.w3.org/TR/REC-xml/#NT-Name
|
16
|
-
TAG_NAME_START_REGEXP_SET = "@:A-Z_a-z\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}" \
|
17
|
-
"\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}" \
|
18
|
-
"\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}"
|
19
|
-
TAG_NAME_START_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}]/
|
20
|
-
TAG_NAME_FOLLOWING_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}]/
|
21
|
-
TAG_NAME_REPLACEMENT_CHAR = "_"
|
22
|
-
|
23
14
|
# A utility method for escaping HTML tag characters.
|
24
15
|
# This method is also aliased as <tt>h</tt>.
|
25
16
|
#
|
@@ -93,7 +84,7 @@ class ERB
|
|
93
84
|
# use inside HTML attributes.
|
94
85
|
#
|
95
86
|
# If your JSON is being used downstream for insertion into the DOM, be aware of
|
96
|
-
# whether or not it is being inserted via
|
87
|
+
# whether or not it is being inserted via <tt>html()</tt>. Most jQuery plugins do this.
|
97
88
|
# If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
|
98
89
|
# content returned by your JSON.
|
99
90
|
#
|
@@ -124,26 +115,6 @@ class ERB
|
|
124
115
|
end
|
125
116
|
|
126
117
|
module_function :json_escape
|
127
|
-
|
128
|
-
# A utility method for escaping XML names of tags and names of attributes.
|
129
|
-
#
|
130
|
-
# xml_name_escape('1 < 2 & 3')
|
131
|
-
# # => "1___2___3"
|
132
|
-
#
|
133
|
-
# It follows the requirements of the specification: https://www.w3.org/TR/REC-xml/#NT-Name
|
134
|
-
def xml_name_escape(name)
|
135
|
-
name = name.to_s
|
136
|
-
return "" if name.blank?
|
137
|
-
|
138
|
-
starting_char = name[0].gsub(TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
|
139
|
-
|
140
|
-
return starting_char if name.size == 1
|
141
|
-
|
142
|
-
following_chars = name[1..-1].gsub(TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
|
143
|
-
|
144
|
-
starting_char + following_chars
|
145
|
-
end
|
146
|
-
module_function :xml_name_escape
|
147
118
|
end
|
148
119
|
end
|
149
120
|
|
@@ -159,7 +130,7 @@ class Numeric
|
|
159
130
|
end
|
160
131
|
end
|
161
132
|
|
162
|
-
module ActiveSupport
|
133
|
+
module ActiveSupport # :nodoc:
|
163
134
|
class SafeBuffer < String
|
164
135
|
UNSAFE_STRING_METHODS = %w(
|
165
136
|
capitalize chomp chop delete delete_prefix delete_suffix
|
@@ -213,27 +184,30 @@ module ActiveSupport #:nodoc:
|
|
213
184
|
end
|
214
185
|
|
215
186
|
def concat(value)
|
216
|
-
|
187
|
+
unless value.nil?
|
188
|
+
super(implicit_html_escape_interpolated_argument(value))
|
189
|
+
end
|
190
|
+
self
|
217
191
|
end
|
218
192
|
alias << concat
|
219
193
|
|
220
194
|
def insert(index, value)
|
221
|
-
super(index,
|
195
|
+
super(index, implicit_html_escape_interpolated_argument(value))
|
222
196
|
end
|
223
197
|
|
224
198
|
def prepend(value)
|
225
|
-
super(
|
199
|
+
super(implicit_html_escape_interpolated_argument(value))
|
226
200
|
end
|
227
201
|
|
228
202
|
def replace(value)
|
229
|
-
super(
|
203
|
+
super(implicit_html_escape_interpolated_argument(value))
|
230
204
|
end
|
231
205
|
|
232
206
|
def []=(*args)
|
233
|
-
if args.
|
234
|
-
super(args[0], args[1],
|
207
|
+
if args.length == 3
|
208
|
+
super(args[0], args[1], implicit_html_escape_interpolated_argument(args[2]))
|
235
209
|
else
|
236
|
-
super(args[0],
|
210
|
+
super(args[0], implicit_html_escape_interpolated_argument(args[1]))
|
237
211
|
end
|
238
212
|
end
|
239
213
|
|
@@ -251,9 +225,9 @@ module ActiveSupport #:nodoc:
|
|
251
225
|
def %(args)
|
252
226
|
case args
|
253
227
|
when Hash
|
254
|
-
escaped_args =
|
228
|
+
escaped_args = args.transform_values { |arg| explicit_html_escape_interpolated_argument(arg) }
|
255
229
|
else
|
256
|
-
escaped_args = Array(args).map { |arg|
|
230
|
+
escaped_args = Array(args).map { |arg| explicit_html_escape_interpolated_argument(arg) }
|
257
231
|
end
|
258
232
|
|
259
233
|
self.class.new(super(escaped_args))
|
@@ -291,39 +265,60 @@ module ActiveSupport #:nodoc:
|
|
291
265
|
end
|
292
266
|
|
293
267
|
UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
EOT
|
319
|
-
end
|
268
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
269
|
+
def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
|
270
|
+
if block # if block
|
271
|
+
to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
|
272
|
+
set_block_back_references(block, $~) # set_block_back_references(block, $~)
|
273
|
+
block.call(*params) # block.call(*params)
|
274
|
+
} # }
|
275
|
+
else # else
|
276
|
+
to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
|
277
|
+
end # end
|
278
|
+
end # end
|
279
|
+
|
280
|
+
def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
|
281
|
+
@html_safe = false # @html_safe = false
|
282
|
+
if block # if block
|
283
|
+
super(*args) { |*params| # super(*args) { |*params|
|
284
|
+
set_block_back_references(block, $~) # set_block_back_references(block, $~)
|
285
|
+
block.call(*params) # block.call(*params)
|
286
|
+
} # }
|
287
|
+
else # else
|
288
|
+
super # super
|
289
|
+
end # end
|
290
|
+
end # end
|
291
|
+
EOT
|
320
292
|
end
|
321
293
|
|
322
294
|
private
|
323
|
-
def
|
295
|
+
def explicit_html_escape_interpolated_argument(arg)
|
324
296
|
(!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
|
325
297
|
end
|
326
298
|
|
299
|
+
def implicit_html_escape_interpolated_argument(arg)
|
300
|
+
if !html_safe? || arg.html_safe?
|
301
|
+
arg
|
302
|
+
else
|
303
|
+
arg_string = begin
|
304
|
+
arg.to_str
|
305
|
+
rescue NoMethodError => error
|
306
|
+
if error.name == :to_str
|
307
|
+
str = arg.to_s
|
308
|
+
ActiveSupport::Deprecation.warn <<~MSG.squish
|
309
|
+
Implicit conversion of #{arg.class} into String by ActiveSupport::SafeBuffer
|
310
|
+
is deprecated and will be removed in Rails 7.1.
|
311
|
+
You must explicitly cast it to a String.
|
312
|
+
MSG
|
313
|
+
str
|
314
|
+
else
|
315
|
+
raise
|
316
|
+
end
|
317
|
+
end
|
318
|
+
CGI.escapeHTML(arg_string)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
327
322
|
def set_block_back_references(block, match_data)
|
328
323
|
block.binding.eval("proc { |m| $~ = m }").call(match_data)
|
329
324
|
rescue ArgumentError
|
@@ -6,6 +6,7 @@ require "active_support/time_with_zone"
|
|
6
6
|
require "active_support/core_ext/time/zones"
|
7
7
|
require "active_support/core_ext/date_and_time/calculations"
|
8
8
|
require "active_support/core_ext/date/calculations"
|
9
|
+
require "active_support/core_ext/module/remove_method"
|
9
10
|
|
10
11
|
class Time
|
11
12
|
include DateAndTime::Calculations
|
@@ -41,8 +42,8 @@ class Time
|
|
41
42
|
|
42
43
|
# Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
|
43
44
|
# instances can be used when called with a single argument
|
44
|
-
def at_with_coercion(*args)
|
45
|
-
return at_without_coercion(*args) if args.size != 1
|
45
|
+
def at_with_coercion(*args, **kwargs)
|
46
|
+
return at_without_coercion(*args, **kwargs) if args.size != 1 || !kwargs.empty?
|
46
47
|
|
47
48
|
# Time.at can be called with a time or numerical value
|
48
49
|
time_or_number = args.first
|
@@ -107,6 +108,21 @@ class Time
|
|
107
108
|
subsec
|
108
109
|
end
|
109
110
|
|
111
|
+
unless Time.method_defined?(:floor)
|
112
|
+
def floor(precision = 0)
|
113
|
+
change(nsec: 0) + subsec.floor(precision)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Restricted Ruby version due to a bug in `Time#ceil`
|
118
|
+
# See https://bugs.ruby-lang.org/issues/17025 for more details
|
119
|
+
if RUBY_VERSION <= "2.8"
|
120
|
+
remove_possible_method :ceil
|
121
|
+
def ceil(precision = 0)
|
122
|
+
change(nsec: 0) + subsec.ceil(precision)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
110
126
|
# Returns a new Time where one or more of the elements have been changed according
|
111
127
|
# to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
|
112
128
|
# <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
|
@@ -143,6 +159,8 @@ class Time
|
|
143
159
|
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
|
144
160
|
elsif utc?
|
145
161
|
::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
|
162
|
+
elsif zone&.respond_to?(:utc_to_local)
|
163
|
+
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
|
146
164
|
elsif zone
|
147
165
|
::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
|
148
166
|
else
|
@@ -259,7 +277,7 @@ class Time
|
|
259
277
|
end
|
260
278
|
alias :at_end_of_minute :end_of_minute
|
261
279
|
|
262
|
-
def plus_with_duration(other)
|
280
|
+
def plus_with_duration(other) # :nodoc:
|
263
281
|
if ActiveSupport::Duration === other
|
264
282
|
other.since(self)
|
265
283
|
else
|
@@ -269,7 +287,7 @@ class Time
|
|
269
287
|
alias_method :plus_without_duration, :+
|
270
288
|
alias_method :+, :plus_with_duration
|
271
289
|
|
272
|
-
def minus_with_duration(other)
|
290
|
+
def minus_with_duration(other) # :nodoc:
|
273
291
|
if ActiveSupport::Duration === other
|
274
292
|
other.until(self)
|
275
293
|
else
|
@@ -287,7 +305,7 @@ class Time
|
|
287
305
|
other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
|
288
306
|
end
|
289
307
|
alias_method :minus_without_coercion, :-
|
290
|
-
alias_method :-, :minus_with_coercion
|
308
|
+
alias_method :-, :minus_with_coercion # rubocop:disable Lint/DuplicateMethods
|
291
309
|
|
292
310
|
# Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
|
293
311
|
# can be chronologically compared with a Time
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "time"
|
3
4
|
require "active_support/inflector/methods"
|
4
5
|
require "active_support/values/time_zone"
|
5
6
|
|
6
7
|
class Time
|
7
8
|
DATE_FORMATS = {
|
8
9
|
db: "%Y-%m-%d %H:%M:%S",
|
10
|
+
inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
|
9
11
|
number: "%Y%m%d%H%M%S",
|
10
12
|
nsec: "%Y%m%d%H%M%S%9N",
|
11
13
|
usec: "%Y%m%d%H%M%S%6N",
|
@@ -25,12 +27,12 @@ class Time
|
|
25
27
|
|
26
28
|
# Converts to a formatted string. See DATE_FORMATS for built-in formats.
|
27
29
|
#
|
28
|
-
# This method is aliased to <tt>
|
30
|
+
# This method is aliased to <tt>to_fs</tt>.
|
29
31
|
#
|
30
32
|
# time = Time.now # => 2007-01-18 06:10:17 -06:00
|
31
33
|
#
|
32
34
|
# time.to_formatted_s(:time) # => "06:10"
|
33
|
-
# time.
|
35
|
+
# time.to_fs(:time) # => "06:10"
|
34
36
|
#
|
35
37
|
# time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
|
36
38
|
# time.to_formatted_s(:number) # => "20070118061017"
|
@@ -52,11 +54,12 @@ class Time
|
|
52
54
|
if formatter = DATE_FORMATS[format]
|
53
55
|
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
54
56
|
else
|
57
|
+
# Change to `to_s` when deprecation is gone. Also deprecate `to_default_s`.
|
55
58
|
to_default_s
|
56
59
|
end
|
57
60
|
end
|
61
|
+
alias_method :to_fs, :to_formatted_s
|
58
62
|
alias_method :to_default_s, :to_s
|
59
|
-
alias_method :to_s, :to_formatted_s
|
60
63
|
|
61
64
|
# Returns a formatted string of the offset from UTC, or an alternative
|
62
65
|
# string if the time zone is already UTC.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "time"
|
4
|
+
|
5
|
+
class Time
|
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
|
+
"Time#to_s(#{format.inspect}) is deprecated. Please use Time#to_formatted_s(#{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
|
+
"Time#to_s(#{format.inspect}) is deprecated. Please use Time#to_formatted_s(#{format.inspect}) instead."
|
18
|
+
)
|
19
|
+
to_default_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -12,7 +12,7 @@ class Time
|
|
12
12
|
# Returns the TimeZone for the current request, if this has been set (via Time.zone=).
|
13
13
|
# If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
|
14
14
|
def zone
|
15
|
-
|
15
|
+
::ActiveSupport::IsolatedExecutionState[:time_zone] || zone_default
|
16
16
|
end
|
17
17
|
|
18
18
|
# Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
|
@@ -39,7 +39,7 @@ class Time
|
|
39
39
|
# end
|
40
40
|
# end
|
41
41
|
def zone=(time_zone)
|
42
|
-
|
42
|
+
::ActiveSupport::IsolatedExecutionState[:time_zone] = find_zone!(time_zone)
|
43
43
|
end
|
44
44
|
|
45
45
|
# Allows override of <tt>Time.zone</tt> locally inside supplied block;
|
@@ -80,24 +80,9 @@ class Time
|
|
80
80
|
# Time.find_zone! false # => false
|
81
81
|
# Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
|
82
82
|
def find_zone!(time_zone)
|
83
|
-
|
84
|
-
time_zone
|
85
|
-
else
|
86
|
-
# Look up the timezone based on the identifier (unless we've been
|
87
|
-
# passed a TZInfo::Timezone)
|
88
|
-
unless time_zone.respond_to?(:period_for_local)
|
89
|
-
time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
|
90
|
-
end
|
83
|
+
return time_zone unless time_zone
|
91
84
|
|
92
|
-
|
93
|
-
if time_zone.is_a?(ActiveSupport::TimeZone)
|
94
|
-
time_zone
|
95
|
-
else
|
96
|
-
ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
rescue TZInfo::InvalidTimezoneIdentifier
|
100
|
-
raise ArgumentError, "Invalid Timezone: #{time_zone}"
|
85
|
+
ActiveSupport::TimeZone[time_zone] || raise(ArgumentError, "Invalid Timezone: #{time_zone}")
|
101
86
|
end
|
102
87
|
|
103
88
|
# Returns a TimeZone instance matching the time zone provided.
|