activesupport 6.0.6.1 → 6.1.7.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +441 -455
- data/MIT-LICENSE +1 -1
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +3 -3
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +3 -3
- data/lib/active_support/cache/mem_cache_store.rb +28 -18
- data/lib/active_support/cache/memory_store.rb +46 -26
- data/lib/active_support/cache/redis_cache_store.rb +25 -25
- data/lib/active_support/cache/strategy/local_cache.rb +20 -5
- data/lib/active_support/cache.rb +87 -40
- data/lib/active_support/callbacks.rb +65 -56
- data/lib/active_support/concern.rb +46 -2
- data/lib/active_support/configurable.rb +3 -3
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +17 -38
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- 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/digest/uuid.rb +1 -0
- data/lib/active_support/core_ext/enumerable.rb +76 -4
- 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 +1 -1
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/marshal.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +38 -28
- data/lib/active_support/core_ext/module/introspection.rb +1 -25
- data/lib/active_support/core_ext/name_error.rb +29 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +12 -1
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/range/compare_range.rb +9 -3
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
- 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/inflections.rb +38 -4
- 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 +7 -4
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +19 -0
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +5 -1
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +9 -2
- data/lib/active_support/dependencies/zeitwerk_integration.rb +4 -1
- data/lib/active_support/dependencies.rb +37 -18
- data/lib/active_support/deprecation/behaviors.rb +15 -2
- 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 +3 -2
- data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/descendants_tracker.rb +6 -2
- data/lib/active_support/digest.rb +2 -0
- data/lib/active_support/duration/iso8601_serializer.rb +15 -9
- data/lib/active_support/duration.rb +75 -25
- data/lib/active_support/encrypted_file.rb +27 -11
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +69 -133
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +48 -24
- data/lib/active_support/i18n_railtie.rb +14 -19
- data/lib/active_support/inflector/inflections.rb +1 -2
- data/lib/active_support/inflector/methods.rb +36 -33
- data/lib/active_support/inflector/transliterate.rb +4 -4
- data/lib/active_support/json/decoding.rb +4 -4
- data/lib/active_support/json/encoding.rb +5 -1
- data/lib/active_support/key_generator.rb +1 -1
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber.rb +8 -0
- 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 -12
- data/lib/active_support/message_encryptor.rb +4 -7
- data/lib/active_support/message_verifier.rb +5 -5
- 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 +4 -42
- data/lib/active_support/multibyte/unicode.rb +9 -83
- data/lib/active_support/notifications/fanout.rb +23 -8
- data/lib/active_support/notifications/instrumenter.rb +6 -15
- data/lib/active_support/notifications.rb +32 -5
- data/lib/active_support/number_helper/number_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 +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 -28
- data/lib/active_support/number_helper.rb +29 -14
- data/lib/active_support/option_merger.rb +2 -1
- data/lib/active_support/ordered_options.rb +8 -2
- data/lib/active_support/parameter_filter.rb +16 -11
- data/lib/active_support/per_thread_registry.rb +2 -1
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +23 -1
- data/lib/active_support/rescuable.rb +4 -4
- 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 +4 -2
- data/lib/active_support/subscriber.rb +12 -7
- data/lib/active_support/tagged_logging.rb +30 -5
- data/lib/active_support/testing/assertions.rb +18 -11
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +12 -95
- data/lib/active_support/testing/time_helpers.rb +40 -3
- data/lib/active_support/time_with_zone.rb +67 -43
- data/lib/active_support/values/time_zone.rb +22 -10
- data/lib/active_support/xml_mini/rexml.rb +8 -1
- data/lib/active_support.rb +13 -1
- metadata +34 -36
- 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/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
@@ -21,13 +21,6 @@ module ActiveSupport
|
|
21
21
|
EOT
|
22
22
|
end
|
23
23
|
|
24
|
-
def after_initialize
|
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
|
-
)
|
29
|
-
end
|
30
|
-
|
31
24
|
def local_log_id
|
32
25
|
Fiber.current.__id__
|
33
26
|
end
|
@@ -37,10 +30,15 @@ module ActiveSupport
|
|
37
30
|
end
|
38
31
|
|
39
32
|
def local_level=(level)
|
40
|
-
|
33
|
+
case level
|
34
|
+
when Integer
|
41
35
|
self.class.local_levels[local_log_id] = level
|
42
|
-
|
36
|
+
when Symbol
|
37
|
+
self.class.local_levels[local_log_id] = Logger::Severity.const_get(level.to_s.upcase)
|
38
|
+
when nil
|
43
39
|
self.class.local_levels.delete(local_log_id)
|
40
|
+
else
|
41
|
+
raise ArgumentError, "Invalid log level: #{level.inspect}"
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
@@ -48,9 +46,33 @@ module ActiveSupport
|
|
48
46
|
local_level || super
|
49
47
|
end
|
50
48
|
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
# Change the thread-local level for the duration of the given block.
|
50
|
+
def log_at(level)
|
51
|
+
old_local_level, self.local_level = local_level, level
|
52
|
+
yield
|
53
|
+
ensure
|
54
|
+
self.local_level = old_local_level
|
55
|
+
end
|
56
|
+
|
57
|
+
# Redefined to check severity against #level, and thus the thread-local level, rather than +@level+.
|
58
|
+
# FIXME: Remove when the minimum Ruby version supports overriding Logger#level.
|
59
|
+
def add(severity, message = nil, progname = nil, &block) #:nodoc:
|
60
|
+
severity ||= UNKNOWN
|
61
|
+
progname ||= @progname
|
62
|
+
|
63
|
+
return true if @logdev.nil? || severity < level
|
64
|
+
|
65
|
+
if message.nil?
|
66
|
+
if block_given?
|
67
|
+
message = yield
|
68
|
+
else
|
69
|
+
message = progname
|
70
|
+
progname = @progname
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
@logdev.write \
|
75
|
+
format_message(format_severity(severity), Time.now, progname, message)
|
54
76
|
end
|
55
77
|
end
|
56
78
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "openssl"
|
4
4
|
require "base64"
|
5
|
-
require "active_support/core_ext/array/extract_options"
|
6
5
|
require "active_support/core_ext/module/attribute_accessors"
|
7
6
|
require "active_support/message_verifier"
|
8
7
|
require "active_support/messages/metadata"
|
@@ -134,15 +133,13 @@ module ActiveSupport
|
|
134
133
|
# * <tt>:digest</tt> - String of digest to use for signing. Default is
|
135
134
|
# +SHA1+. Ignored when using an AEAD cipher like 'aes-256-gcm'.
|
136
135
|
# * <tt>:serializer</tt> - Object serializer to use. Default is +Marshal+.
|
137
|
-
def initialize(secret,
|
138
|
-
options = signature_key_or_options.extract_options!
|
139
|
-
sign_secret = signature_key_or_options.first
|
136
|
+
def initialize(secret, sign_secret = nil, cipher: nil, digest: nil, serializer: nil)
|
140
137
|
@secret = secret
|
141
138
|
@sign_secret = sign_secret
|
142
|
-
@cipher =
|
143
|
-
@digest =
|
139
|
+
@cipher = cipher || self.class.default_cipher
|
140
|
+
@digest = digest || "SHA1" unless aead_mode?
|
144
141
|
@verifier = resolve_verifier
|
145
|
-
@serializer =
|
142
|
+
@serializer = serializer || Marshal
|
146
143
|
end
|
147
144
|
|
148
145
|
# Encrypt and sign a message. We need to sign the message in order to avoid
|
@@ -103,11 +103,11 @@ module ActiveSupport
|
|
103
103
|
|
104
104
|
class InvalidSignature < StandardError; end
|
105
105
|
|
106
|
-
def initialize(secret,
|
106
|
+
def initialize(secret, digest: nil, serializer: nil)
|
107
107
|
raise ArgumentError, "Secret should not be nil." unless secret
|
108
108
|
@secret = secret
|
109
|
-
@digest =
|
110
|
-
@serializer =
|
109
|
+
@digest = digest || "SHA1"
|
110
|
+
@serializer = serializer || Marshal
|
111
111
|
end
|
112
112
|
|
113
113
|
# Checks if a signed message could have been generated by signing an object
|
@@ -178,8 +178,8 @@ module ActiveSupport
|
|
178
178
|
|
179
179
|
# Generates a signed message for the provided value.
|
180
180
|
#
|
181
|
-
# The message is signed with the +MessageVerifier+'s secret.
|
182
|
-
#
|
181
|
+
# The message is signed with the +MessageVerifier+'s secret.
|
182
|
+
# Returns Base64-encoded message joined with the generated signature.
|
183
183
|
#
|
184
184
|
# verifier = ActiveSupport::MessageVerifier.new 's3Krit'
|
185
185
|
# verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772"
|
@@ -3,11 +3,12 @@
|
|
3
3
|
module ActiveSupport
|
4
4
|
module Messages
|
5
5
|
module Rotator # :nodoc:
|
6
|
-
def initialize(
|
7
|
-
super
|
6
|
+
def initialize(*secrets, on_rotation: nil, **options)
|
7
|
+
super(*secrets, **options)
|
8
8
|
|
9
9
|
@options = options
|
10
10
|
@rotations = []
|
11
|
+
@on_rotation = on_rotation
|
11
12
|
end
|
12
13
|
|
13
14
|
def rotate(*secrets, **options)
|
@@ -17,7 +18,7 @@ module ActiveSupport
|
|
17
18
|
module Encryptor
|
18
19
|
include Rotator
|
19
20
|
|
20
|
-
def decrypt_and_verify(*args, on_rotation:
|
21
|
+
def decrypt_and_verify(*args, on_rotation: @on_rotation, **options)
|
21
22
|
super
|
22
23
|
rescue MessageEncryptor::InvalidMessage, MessageVerifier::InvalidSignature
|
23
24
|
run_rotations(on_rotation) { |encryptor| encryptor.decrypt_and_verify(*args, **options) } || raise
|
@@ -32,7 +33,7 @@ module ActiveSupport
|
|
32
33
|
module Verifier
|
33
34
|
include Rotator
|
34
35
|
|
35
|
-
def verified(*args, on_rotation:
|
36
|
+
def verified(*args, on_rotation: @on_rotation, **options)
|
36
37
|
super || run_rotations(on_rotation) { |verifier| verifier.verified(*args, **options) }
|
37
38
|
end
|
38
39
|
|
@@ -46,7 +47,7 @@ module ActiveSupport
|
|
46
47
|
def run_rotations(on_rotation)
|
47
48
|
@rotations.find do |rotation|
|
48
49
|
if message = yield(rotation) rescue next
|
49
|
-
on_rotation
|
50
|
+
on_rotation&.call
|
50
51
|
return message
|
51
52
|
end
|
52
53
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "active_support/json"
|
4
4
|
require "active_support/core_ext/string/access"
|
5
5
|
require "active_support/core_ext/string/behavior"
|
6
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
6
7
|
require "active_support/core_ext/module/delegation"
|
7
8
|
|
8
9
|
module ActiveSupport #:nodoc:
|
@@ -48,7 +49,7 @@ module ActiveSupport #:nodoc:
|
|
48
49
|
alias to_s wrapped_string
|
49
50
|
alias to_str wrapped_string
|
50
51
|
|
51
|
-
delegate :<=>, :=~, :acts_like_string?, to: :wrapped_string
|
52
|
+
delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
|
52
53
|
|
53
54
|
# Creates a new Chars instance by wrapping _string_.
|
54
55
|
def initialize(string)
|
@@ -59,7 +60,7 @@ module ActiveSupport #:nodoc:
|
|
59
60
|
# Forward all undefined methods to the wrapped string.
|
60
61
|
def method_missing(method, *args, &block)
|
61
62
|
result = @wrapped_string.__send__(method, *args, &block)
|
62
|
-
if
|
63
|
+
if method.end_with?("!")
|
63
64
|
self if result
|
64
65
|
else
|
65
66
|
result.kind_of?(String) ? chars(result) : result
|
@@ -73,17 +74,6 @@ module ActiveSupport #:nodoc:
|
|
73
74
|
@wrapped_string.respond_to?(method, include_private)
|
74
75
|
end
|
75
76
|
|
76
|
-
# Returns +true+ when the proxy class can handle the string. Returns
|
77
|
-
# +false+ otherwise.
|
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
|
-
|
84
|
-
string.encoding == Encoding::UTF_8
|
85
|
-
end
|
86
|
-
|
87
77
|
# Works just like <tt>String#split</tt>, with the exception that the items
|
88
78
|
# in the resulting list are Chars instances instead of String. This makes
|
89
79
|
# chaining methods easier.
|
@@ -134,34 +124,6 @@ module ActiveSupport #:nodoc:
|
|
134
124
|
end
|
135
125
|
alias_method :titlecase, :titleize
|
136
126
|
|
137
|
-
# Returns the KC normalization of the string by default. NFKC is
|
138
|
-
# considered the best normalization form for passing strings to databases
|
139
|
-
# and validations.
|
140
|
-
#
|
141
|
-
# * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
|
142
|
-
# <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
|
143
|
-
# ActiveSupport::Multibyte::Unicode.default_normalization_form
|
144
|
-
def normalize(form = nil)
|
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
|
163
|
-
end
|
164
|
-
|
165
127
|
# Performs canonical decomposition on all the characters.
|
166
128
|
#
|
167
129
|
# 'é'.length # => 2
|
@@ -201,7 +163,7 @@ module ActiveSupport #:nodoc:
|
|
201
163
|
|
202
164
|
%w(reverse tidy_bytes).each do |method|
|
203
165
|
define_method("#{method}!") do |*args|
|
204
|
-
@wrapped_string =
|
166
|
+
@wrapped_string = public_send(method, *args).to_s
|
205
167
|
self
|
206
168
|
end
|
207
169
|
end
|
@@ -5,53 +5,19 @@ module ActiveSupport
|
|
5
5
|
module Unicode
|
6
6
|
extend self
|
7
7
|
|
8
|
-
# A list of all available normalization forms.
|
9
|
-
# See https://www.unicode.org/reports/tr15/tr15-29.html for more
|
10
|
-
# information about normalization.
|
11
|
-
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
12
|
-
|
13
|
-
NORMALIZATION_FORM_ALIASES = { # :nodoc:
|
14
|
-
c: :nfc,
|
15
|
-
d: :nfd,
|
16
|
-
kc: :nfkc,
|
17
|
-
kd: :nfkd
|
18
|
-
}
|
19
|
-
|
20
8
|
# The Unicode version that is supported by the implementation
|
21
9
|
UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
|
22
10
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# ActiveSupport::Multibyte::Unicode.default_normalization_form = :c
|
28
|
-
attr_accessor :default_normalization_form
|
29
|
-
@default_normalization_form = :kc
|
30
|
-
|
31
|
-
# Unpack the string at grapheme boundaries. Returns a list of character
|
32
|
-
# lists.
|
33
|
-
#
|
34
|
-
# Unicode.unpack_graphemes('क्षि') # => [[2325, 2381], [2359], [2367]]
|
35
|
-
# Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]]
|
36
|
-
def unpack_graphemes(string)
|
37
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
38
|
-
ActiveSupport::Multibyte::Unicode#unpack_graphemes is deprecated and will be
|
39
|
-
removed from Rails 6.1. Use string.scan(/\X/).map(&:codepoints) instead.
|
40
|
-
MSG
|
41
|
-
|
42
|
-
string.scan(/\X/).map(&:codepoints)
|
11
|
+
def default_normalization_form
|
12
|
+
ActiveSupport::Deprecation.warn(
|
13
|
+
"ActiveSupport::Multibyte::Unicode.default_normalization_form is deprecated and will be removed in Rails 7.0."
|
14
|
+
)
|
43
15
|
end
|
44
16
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
50
|
-
ActiveSupport::Multibyte::Unicode#pack_graphemes is deprecated and will be
|
51
|
-
removed from Rails 6.1. Use array.flatten.pack("U*") instead.
|
52
|
-
MSG
|
53
|
-
|
54
|
-
unpacked.flatten.pack("U*")
|
17
|
+
def default_normalization_form=(_)
|
18
|
+
ActiveSupport::Deprecation.warn(
|
19
|
+
"ActiveSupport::Multibyte::Unicode.default_normalization_form= is deprecated and will be removed in Rails 7.0."
|
20
|
+
)
|
55
21
|
end
|
56
22
|
|
57
23
|
# Decompose composed characters to the decomposed form.
|
@@ -76,7 +42,7 @@ module ActiveSupport
|
|
76
42
|
# Passing +true+ will forcibly tidy all bytes, assuming that the string's
|
77
43
|
# encoding is entirely CP1252 or ISO-8859-1.
|
78
44
|
def tidy_bytes(string, force = false)
|
79
|
-
return string if string.empty?
|
45
|
+
return string if string.empty? || string.ascii_only?
|
80
46
|
return recode_windows1252_chars(string) if force
|
81
47
|
string.scrub { |bad| recode_windows1252_chars(bad) }
|
82
48
|
end
|
@@ -107,46 +73,6 @@ module ActiveSupport
|
|
107
73
|
end
|
108
74
|
end
|
109
75
|
|
110
|
-
# Returns the KC normalization of the string by default. NFKC is
|
111
|
-
# considered the best normalization form for passing strings to databases
|
112
|
-
# and validations.
|
113
|
-
#
|
114
|
-
# * <tt>string</tt> - The string to perform normalization on.
|
115
|
-
# * <tt>form</tt> - The form you want to normalize in. Should be one of
|
116
|
-
# the following: <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>.
|
117
|
-
# Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
|
118
|
-
def normalize(string, form = nil)
|
119
|
-
form ||= @default_normalization_form
|
120
|
-
|
121
|
-
# See https://www.unicode.org/reports/tr15, Table 1
|
122
|
-
if alias_form = NORMALIZATION_FORM_ALIASES[form]
|
123
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
124
|
-
ActiveSupport::Multibyte::Unicode#normalize is deprecated and will be
|
125
|
-
removed from Rails 6.1. Use String#unicode_normalize(:#{alias_form}) instead.
|
126
|
-
MSG
|
127
|
-
|
128
|
-
string.unicode_normalize(alias_form)
|
129
|
-
else
|
130
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
131
|
-
ActiveSupport::Multibyte::Unicode#normalize is deprecated and will be
|
132
|
-
removed from Rails 6.1. Use String#unicode_normalize instead.
|
133
|
-
MSG
|
134
|
-
|
135
|
-
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
%w(downcase upcase swapcase).each do |method|
|
140
|
-
define_method(method) do |string|
|
141
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
142
|
-
ActiveSupport::Multibyte::Unicode##{method} is deprecated and
|
143
|
-
will be removed from Rails 6.1. Use String methods directly.
|
144
|
-
MSG
|
145
|
-
|
146
|
-
string.send(method)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
76
|
private
|
151
77
|
def recode_windows1252_chars(string)
|
152
78
|
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "mutex_m"
|
4
4
|
require "concurrent/map"
|
5
5
|
require "set"
|
6
|
+
require "active_support/core_ext/object/try"
|
6
7
|
|
7
8
|
module ActiveSupport
|
8
9
|
module Notifications
|
@@ -20,8 +21,8 @@ module ActiveSupport
|
|
20
21
|
super
|
21
22
|
end
|
22
23
|
|
23
|
-
def subscribe(pattern = nil, callable = nil, &block)
|
24
|
-
subscriber = Subscribers.new(pattern, callable || block)
|
24
|
+
def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
|
25
|
+
subscriber = Subscribers.new(pattern, callable || block, monotonic)
|
25
26
|
synchronize do
|
26
27
|
if String === pattern
|
27
28
|
@string_subscribers[pattern] << subscriber
|
@@ -84,8 +85,8 @@ module ActiveSupport
|
|
84
85
|
end
|
85
86
|
|
86
87
|
module Subscribers # :nodoc:
|
87
|
-
def self.new(pattern, listener)
|
88
|
-
subscriber_class = Timed
|
88
|
+
def self.new(pattern, listener, monotonic)
|
89
|
+
subscriber_class = monotonic ? MonotonicTimed : Timed
|
89
90
|
|
90
91
|
if listener.respond_to?(:start) && listener.respond_to?(:finish)
|
91
92
|
subscriber_class = Evented
|
@@ -103,10 +104,6 @@ module ActiveSupport
|
|
103
104
|
wrap_all pattern, subscriber_class.new(pattern, listener)
|
104
105
|
end
|
105
106
|
|
106
|
-
def self.event_object_subscriber(pattern, block)
|
107
|
-
wrap_all pattern, EventObject.new(pattern, block)
|
108
|
-
end
|
109
|
-
|
110
107
|
def self.wrap_all(pattern, subscriber)
|
111
108
|
unless pattern
|
112
109
|
AllMessages.new(subscriber)
|
@@ -190,6 +187,23 @@ module ActiveSupport
|
|
190
187
|
end
|
191
188
|
end
|
192
189
|
|
190
|
+
class MonotonicTimed < Evented # :nodoc:
|
191
|
+
def publish(name, *args)
|
192
|
+
@delegate.call name, *args
|
193
|
+
end
|
194
|
+
|
195
|
+
def start(name, id, payload)
|
196
|
+
timestack = Thread.current[:_timestack_monotonic] ||= []
|
197
|
+
timestack.push Concurrent.monotonic_time
|
198
|
+
end
|
199
|
+
|
200
|
+
def finish(name, id, payload)
|
201
|
+
timestack = Thread.current[:_timestack_monotonic]
|
202
|
+
started = timestack.pop
|
203
|
+
@delegate.call(name, started, Concurrent.monotonic_time, id, payload)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
193
207
|
class EventObject < Evented
|
194
208
|
def start(name, id, payload)
|
195
209
|
stack = Thread.current[:_event_stack] ||= []
|
@@ -201,6 +215,7 @@ module ActiveSupport
|
|
201
215
|
def finish(name, id, payload)
|
202
216
|
stack = Thread.current[:_event_stack]
|
203
217
|
event = stack.pop
|
218
|
+
event.payload = payload
|
204
219
|
event.finish!
|
205
220
|
@delegate.call event
|
206
221
|
end
|
@@ -52,14 +52,8 @@ module ActiveSupport
|
|
52
52
|
end
|
53
53
|
|
54
54
|
class Event
|
55
|
-
attr_reader :name, :time, :end, :transaction_id, :
|
56
|
-
|
57
|
-
def self.clock_gettime_supported? # :nodoc:
|
58
|
-
defined?(Process::CLOCK_THREAD_CPUTIME_ID) &&
|
59
|
-
!Gem.win_platform? &&
|
60
|
-
!RUBY_PLATFORM.match?(/solaris/i)
|
61
|
-
end
|
62
|
-
private_class_method :clock_gettime_supported?
|
55
|
+
attr_reader :name, :time, :end, :transaction_id, :children
|
56
|
+
attr_accessor :payload
|
63
57
|
|
64
58
|
def initialize(name, start, ending, transaction_id, payload)
|
65
59
|
@name = name
|
@@ -88,11 +82,6 @@ module ActiveSupport
|
|
88
82
|
@allocation_count_finish = now_allocations
|
89
83
|
end
|
90
84
|
|
91
|
-
def end=(ending)
|
92
|
-
ActiveSupport::Deprecation.deprecation_warning(:end=, :finish!)
|
93
|
-
@end = ending
|
94
|
-
end
|
95
|
-
|
96
85
|
# Returns the CPU time (in milliseconds) passed since the call to
|
97
86
|
# +start!+ and the call to +finish!+
|
98
87
|
def cpu_time
|
@@ -140,11 +129,13 @@ module ActiveSupport
|
|
140
129
|
Concurrent.monotonic_time
|
141
130
|
end
|
142
131
|
|
143
|
-
|
132
|
+
begin
|
133
|
+
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
|
134
|
+
|
144
135
|
def now_cpu
|
145
136
|
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
|
146
137
|
end
|
147
|
-
|
138
|
+
rescue
|
148
139
|
def now_cpu
|
149
140
|
0
|
150
141
|
end
|
@@ -38,6 +38,19 @@ module ActiveSupport
|
|
38
38
|
# payload # => Hash, the payload
|
39
39
|
# end
|
40
40
|
#
|
41
|
+
# Here, the +start+ and +finish+ values represent wall-clock time. If you are
|
42
|
+
# concerned about accuracy, you can register a monotonic subscriber.
|
43
|
+
#
|
44
|
+
# ActiveSupport::Notifications.monotonic_subscribe('render') do |name, start, finish, id, payload|
|
45
|
+
# name # => String, name of the event (such as 'render' from above)
|
46
|
+
# start # => Monotonic time, when the instrumented block started execution
|
47
|
+
# finish # => Monotonic time, when the instrumented block ended execution
|
48
|
+
# id # => String, unique ID for the instrumenter that fired the event
|
49
|
+
# payload # => Hash, the payload
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# The +start+ and +finish+ values above represent monotonic time.
|
53
|
+
#
|
41
54
|
# For instance, let's store all "render" events in an array:
|
42
55
|
#
|
43
56
|
# events = []
|
@@ -135,6 +148,16 @@ module ActiveSupport
|
|
135
148
|
# during the execution of the block. The callback is unsubscribed automatically
|
136
149
|
# after that.
|
137
150
|
#
|
151
|
+
# To record +started+ and +finished+ values with monotonic time,
|
152
|
+
# specify the optional <tt>:monotonic</tt> option to the
|
153
|
+
# <tt>subscribed</tt> method. The <tt>:monotonic</tt> option is set
|
154
|
+
# to +false+ by default.
|
155
|
+
#
|
156
|
+
# callback = lambda {|name, started, finished, unique_id, payload| ... }
|
157
|
+
# ActiveSupport::Notifications.subscribed(callback, "sql.active_record", monotonic: true) do
|
158
|
+
# ...
|
159
|
+
# end
|
160
|
+
#
|
138
161
|
# === Manual Unsubscription
|
139
162
|
#
|
140
163
|
# The +subscribe+ method returns a subscriber object:
|
@@ -155,7 +178,7 @@ module ActiveSupport
|
|
155
178
|
#
|
156
179
|
# Subscribers using a regexp or other pattern-matching object will remain subscribed
|
157
180
|
# to all events that match their original pattern, unless those events match a string
|
158
|
-
# passed to
|
181
|
+
# passed to +unsubscribe+:
|
159
182
|
#
|
160
183
|
# subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
|
161
184
|
# ActiveSupport::Notifications.unsubscribe('render_template.action_view')
|
@@ -208,12 +231,16 @@ module ActiveSupport
|
|
208
231
|
# ActiveSupport::Notifications.subscribe(/render/) do |event|
|
209
232
|
# @event = event
|
210
233
|
# end
|
211
|
-
def subscribe(
|
212
|
-
notifier.subscribe(
|
234
|
+
def subscribe(pattern = nil, callback = nil, &block)
|
235
|
+
notifier.subscribe(pattern, callback, monotonic: false, &block)
|
236
|
+
end
|
237
|
+
|
238
|
+
def monotonic_subscribe(pattern = nil, callback = nil, &block)
|
239
|
+
notifier.subscribe(pattern, callback, monotonic: true, &block)
|
213
240
|
end
|
214
241
|
|
215
|
-
def subscribed(callback,
|
216
|
-
subscriber = subscribe(
|
242
|
+
def subscribed(callback, pattern = nil, monotonic: false, &block)
|
243
|
+
subscriber = notifier.subscribe(pattern, callback, monotonic: monotonic)
|
217
244
|
yield
|
218
245
|
ensure
|
219
246
|
unsubscribe(subscriber)
|
@@ -30,7 +30,7 @@ module ActiveSupport
|
|
30
30
|
# If set to true, precision will mean the number of significant digits instead
|
31
31
|
# of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
|
32
32
|
significant: false,
|
33
|
-
# If set, the zeros after the decimal separator will always be stripped (
|
33
|
+
# If set, the zeros after the decimal separator will always be stripped (e.g.: 1.200 will be 1.2)
|
34
34
|
strip_insignificant_zeros: false
|
35
35
|
},
|
36
36
|
|
@@ -16,7 +16,7 @@ module ActiveSupport
|
|
16
16
|
@number = RoundingHelper.new(options).round(number)
|
17
17
|
@number = Float(number)
|
18
18
|
|
19
|
-
#
|
19
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
20
20
|
unless options.key?(:strip_insignificant_zeros)
|
21
21
|
options[:strip_insignificant_zeros] = true
|
22
22
|
end
|
@@ -13,7 +13,7 @@ module ActiveSupport
|
|
13
13
|
def convert
|
14
14
|
@number = Float(number)
|
15
15
|
|
16
|
-
#
|
16
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
17
17
|
unless options.key?(:strip_insignificant_zeros)
|
18
18
|
options[:strip_insignificant_zeros] = true
|
19
19
|
end
|
@@ -20,14 +20,18 @@ module ActiveSupport
|
|
20
20
|
end
|
21
21
|
|
22
22
|
formatted_string =
|
23
|
-
if
|
23
|
+
if rounded_number.finite?
|
24
24
|
s = rounded_number.to_s("F")
|
25
|
-
s << "0" * precision
|
26
25
|
a, b = s.split(".", 2)
|
27
|
-
|
28
|
-
|
26
|
+
if precision != 0
|
27
|
+
b << "0" * precision
|
28
|
+
a << "."
|
29
|
+
a << b[0, precision]
|
30
|
+
end
|
31
|
+
a
|
29
32
|
else
|
30
|
-
|
33
|
+
# Infinity/NaN
|
34
|
+
"%f" % rounded_number
|
31
35
|
end
|
32
36
|
else
|
33
37
|
formatted_string = rounded_number
|