activesupport 5.2.4 → 6.0.0
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 +331 -396
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -2
- data/lib/active_support.rb +2 -1
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +28 -1
- data/lib/active_support/cache.rb +45 -23
- data/lib/active_support/cache/file_store.rb +22 -22
- data/lib/active_support/cache/mem_cache_store.rb +5 -0
- data/lib/active_support/cache/memory_store.rb +7 -2
- data/lib/active_support/cache/null_store.rb +5 -0
- data/lib/active_support/cache/redis_cache_store.rb +36 -9
- data/lib/active_support/callbacks.rb +16 -5
- data/lib/active_support/concern.rb +24 -1
- data/lib/active_support/configurable.rb +7 -11
- data/lib/active_support/core_ext/array.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
- data/lib/active_support/core_ext/class/attribute.rb +11 -16
- data/lib/active_support/core_ext/class/subclasses.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -47
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +97 -73
- data/lib/active_support/core_ext/hash.rb +1 -2
- data/lib/active_support/core_ext/hash/compact.rb +2 -26
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +0 -29
- data/lib/active_support/core_ext/hash/slice.rb +3 -25
- data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
- data/lib/active_support/core_ext/integer/multiple.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -10
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +13 -19
- data/lib/active_support/core_ext/module/delegation.rb +33 -7
- data/lib/active_support/core_ext/module/introspection.rb +37 -13
- data/lib/active_support/core_ext/module/reachable.rb +1 -6
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
- data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
- data/lib/active_support/core_ext/object/blank.rb +1 -2
- data/lib/active_support/core_ext/object/duplicable.rb +7 -114
- data/lib/active_support/core_ext/object/json.rb +1 -0
- data/lib/active_support/core_ext/object/try.rb +15 -7
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/compare_range.rb +22 -13
- data/lib/active_support/core_ext/range/conversions.rb +31 -29
- data/lib/active_support/core_ext/range/include_range.rb +6 -0
- data/lib/active_support/core_ext/regexp.rb +0 -4
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +8 -0
- data/lib/active_support/core_ext/string/filters.rb +42 -1
- data/lib/active_support/core_ext/string/inflections.rb +7 -2
- data/lib/active_support/core_ext/string/multibyte.rb +4 -3
- data/lib/active_support/core_ext/string/output_safety.rb +61 -5
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +31 -2
- data/lib/active_support/core_ext/uri.rb +1 -0
- data/lib/active_support/current_attributes.rb +8 -0
- data/lib/active_support/dependencies.rb +69 -16
- data/lib/active_support/dependencies/zeitwerk_integration.rb +110 -0
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/deprecation/behaviors.rb +1 -1
- data/lib/active_support/deprecation/method_wrappers.rb +8 -20
- data/lib/active_support/deprecation/proxy_wrappers.rb +24 -5
- data/lib/active_support/descendants_tracker.rb +56 -9
- data/lib/active_support/duration.rb +4 -3
- data/lib/active_support/duration/iso8601_parser.rb +2 -3
- data/lib/active_support/duration/iso8601_serializer.rb +3 -4
- data/lib/active_support/encrypted_configuration.rb +0 -4
- data/lib/active_support/encrypted_file.rb +2 -1
- data/lib/active_support/evented_file_update_checker.rb +39 -9
- data/lib/active_support/execution_wrapper.rb +1 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +22 -18
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +9 -1
- data/lib/active_support/inflector/inflections.rb +1 -4
- data/lib/active_support/inflector/methods.rb +15 -27
- data/lib/active_support/inflector/transliterate.rb +47 -18
- data/lib/active_support/json/decoding.rb +23 -23
- data/lib/active_support/json/encoding.rb +6 -2
- data/lib/active_support/key_generator.rb +0 -32
- data/lib/active_support/lazy_load_hooks.rb +5 -1
- data/lib/active_support/locale/en.rb +31 -0
- data/lib/active_support/log_subscriber.rb +31 -8
- data/lib/active_support/logger.rb +0 -15
- data/lib/active_support/logger_silence.rb +28 -12
- data/lib/active_support/logger_thread_safe_level.rb +26 -4
- data/lib/active_support/message_encryptor.rb +3 -5
- data/lib/active_support/message_verifier.rb +3 -3
- data/lib/active_support/multibyte/chars.rb +29 -48
- data/lib/active_support/multibyte/unicode.rb +44 -281
- data/lib/active_support/notifications.rb +41 -4
- data/lib/active_support/notifications/fanout.rb +98 -13
- data/lib/active_support/notifications/instrumenter.rb +79 -8
- data/lib/active_support/number_helper.rb +7 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -3
- data/lib/active_support/ordered_options.rb +1 -1
- data/lib/active_support/parameter_filter.rb +129 -0
- data/lib/active_support/rails.rb +0 -6
- data/lib/active_support/reloader.rb +4 -5
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/subscriber.rb +65 -26
- data/lib/active_support/tagged_logging.rb +13 -4
- data/lib/active_support/test_case.rb +91 -0
- data/lib/active_support/testing/assertions.rb +15 -1
- data/lib/active_support/testing/deprecation.rb +0 -1
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +28 -1
- data/lib/active_support/testing/parallelization.rb +128 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +7 -7
- data/lib/active_support/time_with_zone.rb +15 -5
- data/lib/active_support/values/time_zone.rb +12 -7
- data/lib/active_support/xml_mini.rb +2 -9
- data/lib/active_support/xml_mini/jdom.rb +2 -2
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
- data/lib/active_support/xml_mini/rexml.rb +2 -2
- metadata +34 -9
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
{
|
4
|
+
en: {
|
5
|
+
number: {
|
6
|
+
nth: {
|
7
|
+
ordinals: lambda do |_key, number:, **_options|
|
8
|
+
case number
|
9
|
+
when 1; "st"
|
10
|
+
when 2; "nd"
|
11
|
+
when 3; "rd"
|
12
|
+
when 4, 5, 6, 7, 8, 9, 10, 11, 12, 13; "th"
|
13
|
+
else
|
14
|
+
num_modulo = number.to_i.abs % 100
|
15
|
+
num_modulo %= 10 if num_modulo > 13
|
16
|
+
case num_modulo
|
17
|
+
when 1; "st"
|
18
|
+
when 2; "nd"
|
19
|
+
when 3; "rd"
|
20
|
+
else "th"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end,
|
24
|
+
|
25
|
+
ordinalized: lambda do |_key, number:, **_options|
|
26
|
+
"#{number}#{ActiveSupport::Inflector.ordinal(number)}"
|
27
|
+
end
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
@@ -5,8 +5,8 @@ require "active_support/core_ext/class/attribute"
|
|
5
5
|
require "active_support/subscriber"
|
6
6
|
|
7
7
|
module ActiveSupport
|
8
|
-
# ActiveSupport::LogSubscriber is an object set to consume
|
9
|
-
# ActiveSupport::Notifications with the sole purpose of logging them.
|
8
|
+
# <tt>ActiveSupport::LogSubscriber</tt> is an object set to consume
|
9
|
+
# <tt>ActiveSupport::Notifications</tt> with the sole purpose of logging them.
|
10
10
|
# The log subscriber dispatches notifications to a registered object based
|
11
11
|
# on its given namespace.
|
12
12
|
#
|
@@ -16,7 +16,7 @@ module ActiveSupport
|
|
16
16
|
# module ActiveRecord
|
17
17
|
# class LogSubscriber < ActiveSupport::LogSubscriber
|
18
18
|
# def sql(event)
|
19
|
-
# "#{event.payload[:name]} (#{event.duration}) #{event.payload[:sql]}"
|
19
|
+
# info "#{event.payload[:name]} (#{event.duration}) #{event.payload[:sql]}"
|
20
20
|
# end
|
21
21
|
# end
|
22
22
|
# end
|
@@ -29,13 +29,36 @@ module ActiveSupport
|
|
29
29
|
# subscriber, the line above should be called after your
|
30
30
|
# <tt>ActiveRecord::LogSubscriber</tt> definition.
|
31
31
|
#
|
32
|
-
# After configured, whenever a "sql.active_record" notification is published,
|
33
|
-
# it will properly dispatch the event
|
34
|
-
# the sql method.
|
32
|
+
# After configured, whenever a <tt>"sql.active_record"</tt> notification is published,
|
33
|
+
# it will properly dispatch the event
|
34
|
+
# (<tt>ActiveSupport::Notifications::Event</tt>) to the sql method.
|
35
|
+
#
|
36
|
+
# Being an <tt>ActiveSupport::Notifications</tt> consumer,
|
37
|
+
# <tt>ActiveSupport::LogSubscriber</tt> exposes a simple interface to check if
|
38
|
+
# instrumented code raises an exception. It is common to log a different
|
39
|
+
# message in case of an error, and this can be achieved by extending
|
40
|
+
# the previous example:
|
41
|
+
#
|
42
|
+
# module ActiveRecord
|
43
|
+
# class LogSubscriber < ActiveSupport::LogSubscriber
|
44
|
+
# def sql(event)
|
45
|
+
# exception = event.payload[:exception]
|
46
|
+
#
|
47
|
+
# if exception
|
48
|
+
# exception_object = event.payload[:exception_object]
|
49
|
+
#
|
50
|
+
# error "[ERROR] #{event.payload[:name]}: #{exception.join(', ')} " \
|
51
|
+
# "(#{exception_object.backtrace.first})"
|
52
|
+
# else
|
53
|
+
# # standard logger code
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
# end
|
35
58
|
#
|
36
59
|
# Log subscriber also has some helpers to deal with logging and automatically
|
37
|
-
# flushes all logs when the request finishes
|
38
|
-
# notification) in a Rails environment.
|
60
|
+
# flushes all logs when the request finishes
|
61
|
+
# (via <tt>action_dispatch.callback</tt> notification) in a Rails environment.
|
39
62
|
class LogSubscriber < Subscriber
|
40
63
|
# Embed in a String to clear all previous ANSI sequences.
|
41
64
|
CLEAR = "\e[0m"
|
@@ -6,7 +6,6 @@ require "logger"
|
|
6
6
|
|
7
7
|
module ActiveSupport
|
8
8
|
class Logger < ::Logger
|
9
|
-
include ActiveSupport::LoggerThreadSafeLevel
|
10
9
|
include LoggerSilence
|
11
10
|
|
12
11
|
# Returns true if the logger destination matches one of the sources
|
@@ -81,20 +80,6 @@ module ActiveSupport
|
|
81
80
|
def initialize(*args)
|
82
81
|
super
|
83
82
|
@formatter = SimpleFormatter.new
|
84
|
-
after_initialize if respond_to? :after_initialize
|
85
|
-
end
|
86
|
-
|
87
|
-
def add(severity, message = nil, progname = nil, &block)
|
88
|
-
return true if @logdev.nil? || (severity || UNKNOWN) < level
|
89
|
-
super
|
90
|
-
end
|
91
|
-
|
92
|
-
Logger::Severity.constants.each do |severity|
|
93
|
-
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
94
|
-
def #{severity.downcase}? # def debug?
|
95
|
-
Logger::#{severity} >= level # DEBUG >= level
|
96
|
-
end # end
|
97
|
-
EOT
|
98
83
|
end
|
99
84
|
|
100
85
|
# Simple formatter which only displays the message.
|
@@ -2,28 +2,44 @@
|
|
2
2
|
|
3
3
|
require "active_support/concern"
|
4
4
|
require "active_support/core_ext/module/attribute_accessors"
|
5
|
-
require "
|
5
|
+
require "active_support/logger_thread_safe_level"
|
6
6
|
|
7
7
|
module LoggerSilence
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
included do
|
11
|
-
|
11
|
+
ActiveSupport::Deprecation.warn(
|
12
|
+
"Including LoggerSilence is deprecated and will be removed in Rails 6.1. " \
|
13
|
+
"Please use `ActiveSupport::LoggerSilence` instead"
|
14
|
+
)
|
15
|
+
|
16
|
+
include ActiveSupport::LoggerSilence
|
12
17
|
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ActiveSupport
|
21
|
+
module LoggerSilence
|
22
|
+
extend ActiveSupport::Concern
|
23
|
+
|
24
|
+
included do
|
25
|
+
cattr_accessor :silencer, default: true
|
26
|
+
include ActiveSupport::LoggerThreadSafeLevel
|
27
|
+
end
|
13
28
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
29
|
+
# Silences the logger for the duration of the block.
|
30
|
+
def silence(temporary_level = Logger::ERROR)
|
31
|
+
if silencer
|
32
|
+
begin
|
33
|
+
old_local_level = local_level
|
34
|
+
self.local_level = temporary_level
|
20
35
|
|
36
|
+
yield self
|
37
|
+
ensure
|
38
|
+
self.local_level = old_local_level
|
39
|
+
end
|
40
|
+
else
|
21
41
|
yield self
|
22
|
-
ensure
|
23
|
-
self.local_level = old_local_level
|
24
42
|
end
|
25
|
-
else
|
26
|
-
yield self
|
27
43
|
end
|
28
44
|
end
|
29
45
|
end
|
@@ -1,14 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/concern"
|
4
|
+
require "active_support/core_ext/module/attribute_accessors"
|
5
|
+
require "concurrent"
|
4
6
|
require "fiber"
|
5
7
|
|
6
8
|
module ActiveSupport
|
7
9
|
module LoggerThreadSafeLevel # :nodoc:
|
8
10
|
extend ActiveSupport::Concern
|
9
11
|
|
12
|
+
included do
|
13
|
+
cattr_accessor :local_levels, default: Concurrent::Map.new(initial_capacity: 2), instance_accessor: false
|
14
|
+
end
|
15
|
+
|
16
|
+
Logger::Severity.constants.each do |severity|
|
17
|
+
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
18
|
+
def #{severity.downcase}? # def debug?
|
19
|
+
Logger::#{severity} >= level # DEBUG >= level
|
20
|
+
end # end
|
21
|
+
EOT
|
22
|
+
end
|
23
|
+
|
10
24
|
def after_initialize
|
11
|
-
|
25
|
+
ActiveSupport::Deprecation.warn(
|
26
|
+
"Logger don't need to call #after_initialize directly anymore. It will be deprecated without replacement in " \
|
27
|
+
"Rails 6.1."
|
28
|
+
)
|
12
29
|
end
|
13
30
|
|
14
31
|
def local_log_id
|
@@ -16,19 +33,24 @@ module ActiveSupport
|
|
16
33
|
end
|
17
34
|
|
18
35
|
def local_level
|
19
|
-
|
36
|
+
self.class.local_levels[local_log_id]
|
20
37
|
end
|
21
38
|
|
22
39
|
def local_level=(level)
|
23
40
|
if level
|
24
|
-
|
41
|
+
self.class.local_levels[local_log_id] = level
|
25
42
|
else
|
26
|
-
|
43
|
+
self.class.local_levels.delete(local_log_id)
|
27
44
|
end
|
28
45
|
end
|
29
46
|
|
30
47
|
def level
|
31
48
|
local_level || super
|
32
49
|
end
|
50
|
+
|
51
|
+
def add(severity, message = nil, progname = nil, &block) # :nodoc:
|
52
|
+
return true if @logdev.nil? || (severity || UNKNOWN) < level
|
53
|
+
super
|
54
|
+
end
|
33
55
|
end
|
34
56
|
end
|
@@ -53,7 +53,7 @@ module ActiveSupport
|
|
53
53
|
# crypt.encrypt_and_sign(parcel, expires_in: 1.month)
|
54
54
|
# crypt.encrypt_and_sign(doowad, expires_at: Time.now.end_of_year)
|
55
55
|
#
|
56
|
-
# Then the messages can be verified and returned
|
56
|
+
# Then the messages can be verified and returned up to the expire time.
|
57
57
|
# Thereafter, verifying returns +nil+.
|
58
58
|
#
|
59
59
|
# === Rotating keys
|
@@ -182,7 +182,7 @@ module ActiveSupport
|
|
182
182
|
|
183
183
|
def _decrypt(encrypted_message, purpose)
|
184
184
|
cipher = new_cipher
|
185
|
-
encrypted_data, iv, auth_tag = encrypted_message.split("--"
|
185
|
+
encrypted_data, iv, auth_tag = encrypted_message.split("--").map { |v| ::Base64.strict_decode64(v) }
|
186
186
|
|
187
187
|
# Currently the OpenSSL bindings do not raise an error if auth_tag is
|
188
188
|
# truncated, which would allow an attacker to easily forge it. See
|
@@ -210,9 +210,7 @@ module ActiveSupport
|
|
210
210
|
OpenSSL::Cipher.new(@cipher)
|
211
211
|
end
|
212
212
|
|
213
|
-
|
214
|
-
@verifier
|
215
|
-
end
|
213
|
+
attr_reader :verifier
|
216
214
|
|
217
215
|
def aead_mode?
|
218
216
|
@aead_mode ||= new_cipher.authenticated?
|
@@ -71,7 +71,7 @@ module ActiveSupport
|
|
71
71
|
# @verifier.generate(parcel, expires_in: 1.month)
|
72
72
|
# @verifier.generate(doowad, expires_at: Time.now.end_of_year)
|
73
73
|
#
|
74
|
-
# Then the messages can be verified and returned
|
74
|
+
# Then the messages can be verified and returned up to the expire time.
|
75
75
|
# Thereafter, the +verified+ method returns +nil+ while +verify+ raises
|
76
76
|
# <tt>ActiveSupport::MessageVerifier::InvalidSignature</tt>.
|
77
77
|
#
|
@@ -122,7 +122,7 @@ module ActiveSupport
|
|
122
122
|
def valid_message?(signed_message)
|
123
123
|
return if signed_message.nil? || !signed_message.valid_encoding? || signed_message.blank?
|
124
124
|
|
125
|
-
data, digest = signed_message.split("--"
|
125
|
+
data, digest = signed_message.split("--")
|
126
126
|
data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data))
|
127
127
|
end
|
128
128
|
|
@@ -150,7 +150,7 @@ module ActiveSupport
|
|
150
150
|
def verified(signed_message, purpose: nil, **)
|
151
151
|
if valid_message?(signed_message)
|
152
152
|
begin
|
153
|
-
data = signed_message.split("--"
|
153
|
+
data = signed_message.split("--")[0]
|
154
154
|
message = Messages::Metadata.verify(decode(data), purpose)
|
155
155
|
@serializer.load(message) if message
|
156
156
|
rescue ArgumentError => argument_error
|
@@ -4,7 +4,6 @@ require "active_support/json"
|
|
4
4
|
require "active_support/core_ext/string/access"
|
5
5
|
require "active_support/core_ext/string/behavior"
|
6
6
|
require "active_support/core_ext/module/delegation"
|
7
|
-
require "active_support/core_ext/regexp"
|
8
7
|
|
9
8
|
module ActiveSupport #:nodoc:
|
10
9
|
module Multibyte #:nodoc:
|
@@ -18,7 +17,7 @@ module ActiveSupport #:nodoc:
|
|
18
17
|
# through the +mb_chars+ method. Methods which would normally return a
|
19
18
|
# String object now return a Chars object so methods can be chained.
|
20
19
|
#
|
21
|
-
# 'The Perfect String '.mb_chars.downcase.strip
|
20
|
+
# 'The Perfect String '.mb_chars.downcase.strip
|
22
21
|
# # => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
|
23
22
|
#
|
24
23
|
# Chars objects are perfectly interchangeable with String objects as long as
|
@@ -77,6 +76,11 @@ module ActiveSupport #:nodoc:
|
|
77
76
|
# Returns +true+ when the proxy class can handle the string. Returns
|
78
77
|
# +false+ otherwise.
|
79
78
|
def self.consumes?(string)
|
79
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
80
|
+
ActiveSupport::Multibyte::Chars.consumes? is deprecated and will be
|
81
|
+
removed from Rails 6.1. Use string.is_utf8? instead.
|
82
|
+
MSG
|
83
|
+
|
80
84
|
string.encoding == Encoding::UTF_8
|
81
85
|
end
|
82
86
|
|
@@ -109,7 +113,7 @@ module ActiveSupport #:nodoc:
|
|
109
113
|
#
|
110
114
|
# 'Café'.mb_chars.reverse.to_s # => 'éfaC'
|
111
115
|
def reverse
|
112
|
-
chars(
|
116
|
+
chars(@wrapped_string.scan(/\X/).reverse.join)
|
113
117
|
end
|
114
118
|
|
115
119
|
# Limits the byte size of the string to a number of bytes without breaking
|
@@ -118,35 +122,7 @@ module ActiveSupport #:nodoc:
|
|
118
122
|
#
|
119
123
|
# 'こんにちは'.mb_chars.limit(7).to_s # => "こん"
|
120
124
|
def limit(limit)
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
# Converts characters in the string to uppercase.
|
125
|
-
#
|
126
|
-
# 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s # => "LAURENT, OÙ SONT LES TESTS ?"
|
127
|
-
def upcase
|
128
|
-
chars Unicode.upcase(@wrapped_string)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Converts characters in the string to lowercase.
|
132
|
-
#
|
133
|
-
# 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s # => "věda a výzkum"
|
134
|
-
def downcase
|
135
|
-
chars Unicode.downcase(@wrapped_string)
|
136
|
-
end
|
137
|
-
|
138
|
-
# Converts characters in the string to the opposite case.
|
139
|
-
#
|
140
|
-
# 'El Cañón'.mb_chars.swapcase.to_s # => "eL cAÑÓN"
|
141
|
-
def swapcase
|
142
|
-
chars Unicode.swapcase(@wrapped_string)
|
143
|
-
end
|
144
|
-
|
145
|
-
# Converts the first character to uppercase and the remainder to lowercase.
|
146
|
-
#
|
147
|
-
# 'über'.mb_chars.capitalize.to_s # => "Über"
|
148
|
-
def capitalize
|
149
|
-
(slice(0) || chars("")).upcase + (slice(1..-1) || chars("")).downcase
|
125
|
+
truncate_bytes(limit, omission: nil)
|
150
126
|
end
|
151
127
|
|
152
128
|
# Capitalizes the first letter of every word, when possible.
|
@@ -154,7 +130,7 @@ module ActiveSupport #:nodoc:
|
|
154
130
|
# "ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s # => "Él Que Se Enteró"
|
155
131
|
# "日本語".mb_chars.titleize.to_s # => "日本語"
|
156
132
|
def titleize
|
157
|
-
chars(downcase.to_s.gsub(/\b('?\S)/u) {
|
133
|
+
chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
|
158
134
|
end
|
159
135
|
alias_method :titlecase, :titleize
|
160
136
|
|
@@ -166,7 +142,24 @@ module ActiveSupport #:nodoc:
|
|
166
142
|
# <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
|
167
143
|
# ActiveSupport::Multibyte::Unicode.default_normalization_form
|
168
144
|
def normalize(form = nil)
|
169
|
-
|
145
|
+
form ||= Unicode.default_normalization_form
|
146
|
+
|
147
|
+
# See https://www.unicode.org/reports/tr15, Table 1
|
148
|
+
if alias_form = Unicode::NORMALIZATION_FORM_ALIASES[form]
|
149
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
150
|
+
ActiveSupport::Multibyte::Chars#normalize is deprecated and will be
|
151
|
+
removed from Rails 6.1. Use #unicode_normalize(:#{alias_form}) instead.
|
152
|
+
MSG
|
153
|
+
|
154
|
+
send(:unicode_normalize, alias_form)
|
155
|
+
else
|
156
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
157
|
+
ActiveSupport::Multibyte::Chars#normalize is deprecated and will be
|
158
|
+
removed from Rails 6.1. Use #unicode_normalize instead.
|
159
|
+
MSG
|
160
|
+
|
161
|
+
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
162
|
+
end
|
170
163
|
end
|
171
164
|
|
172
165
|
# Performs canonical decomposition on all the characters.
|
@@ -190,7 +183,7 @@ module ActiveSupport #:nodoc:
|
|
190
183
|
# 'क्षि'.mb_chars.length # => 4
|
191
184
|
# 'क्षि'.mb_chars.grapheme_length # => 3
|
192
185
|
def grapheme_length
|
193
|
-
|
186
|
+
@wrapped_string.scan(/\X/).length
|
194
187
|
end
|
195
188
|
|
196
189
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
|
@@ -206,7 +199,7 @@ module ActiveSupport #:nodoc:
|
|
206
199
|
to_s.as_json(options)
|
207
200
|
end
|
208
201
|
|
209
|
-
%w(
|
202
|
+
%w(reverse tidy_bytes).each do |method|
|
210
203
|
define_method("#{method}!") do |*args|
|
211
204
|
@wrapped_string = send(method, *args).to_s
|
212
205
|
self
|
@@ -215,18 +208,6 @@ module ActiveSupport #:nodoc:
|
|
215
208
|
|
216
209
|
private
|
217
210
|
|
218
|
-
def translate_offset(byte_offset)
|
219
|
-
return nil if byte_offset.nil?
|
220
|
-
return 0 if @wrapped_string == ""
|
221
|
-
|
222
|
-
begin
|
223
|
-
@wrapped_string.byteslice(0...byte_offset).unpack("U*").length
|
224
|
-
rescue ArgumentError
|
225
|
-
byte_offset -= 1
|
226
|
-
retry
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
211
|
def chars(string)
|
231
212
|
self.class.new(string)
|
232
213
|
end
|