activesupport 5.2.4 → 6.0.2.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 +391 -395
- 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 +9 -2
- data/lib/active_support/cache/null_store.rb +5 -0
- data/lib/active_support/cache/redis_cache_store.rb +37 -10
- 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 +28 -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/range/include_time_with_zone.rb +2 -2
- 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 +63 -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 +118 -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 +6 -5
- 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 +4 -4
- 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 +13 -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 +80 -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_hash.rb +1 -1
- 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 +30 -8
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -6,12 +6,19 @@ module ActiveSupport
|
|
6
6
|
extend self
|
7
7
|
|
8
8
|
# A list of all available normalization forms.
|
9
|
-
# See
|
9
|
+
# See https://www.unicode.org/reports/tr15/tr15-29.html for more
|
10
10
|
# information about normalization.
|
11
11
|
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
12
12
|
|
13
|
+
NORMALIZATION_FORM_ALIASES = { # :nodoc:
|
14
|
+
c: :nfc,
|
15
|
+
d: :nfd,
|
16
|
+
kc: :nfkc,
|
17
|
+
kd: :nfkd
|
18
|
+
}
|
19
|
+
|
13
20
|
# The Unicode version that is supported by the implementation
|
14
|
-
UNICODE_VERSION = "
|
21
|
+
UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
|
15
22
|
|
16
23
|
# The default normalization used for operations that require
|
17
24
|
# normalization. It can be set to any of the normalizations
|
@@ -21,199 +28,44 @@ module ActiveSupport
|
|
21
28
|
attr_accessor :default_normalization_form
|
22
29
|
@default_normalization_form = :kc
|
23
30
|
|
24
|
-
# Hangul character boundaries and properties
|
25
|
-
HANGUL_SBASE = 0xAC00
|
26
|
-
HANGUL_LBASE = 0x1100
|
27
|
-
HANGUL_VBASE = 0x1161
|
28
|
-
HANGUL_TBASE = 0x11A7
|
29
|
-
HANGUL_LCOUNT = 19
|
30
|
-
HANGUL_VCOUNT = 21
|
31
|
-
HANGUL_TCOUNT = 28
|
32
|
-
HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
|
33
|
-
HANGUL_SCOUNT = 11172
|
34
|
-
HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
|
35
|
-
|
36
|
-
# Detect whether the codepoint is in a certain character class. Returns
|
37
|
-
# +true+ when it's in the specified character class and +false+ otherwise.
|
38
|
-
# Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
|
39
|
-
# <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
|
40
|
-
#
|
41
|
-
# Primarily used by the grapheme cluster support.
|
42
|
-
def in_char_class?(codepoint, classes)
|
43
|
-
classes.detect { |c| database.boundary[c] === codepoint } ? true : false
|
44
|
-
end
|
45
|
-
|
46
31
|
# Unpack the string at grapheme boundaries. Returns a list of character
|
47
32
|
# lists.
|
48
33
|
#
|
49
34
|
# Unicode.unpack_graphemes('क्षि') # => [[2325, 2381], [2359], [2367]]
|
50
35
|
# Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]]
|
51
36
|
def unpack_graphemes(string)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
eoc = codepoints.length
|
57
|
-
while (pos < eoc)
|
58
|
-
pos += 1
|
59
|
-
previous = codepoints[pos - 1]
|
60
|
-
current = codepoints[pos]
|
61
|
-
|
62
|
-
# See http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules
|
63
|
-
should_break =
|
64
|
-
if pos == eoc
|
65
|
-
true
|
66
|
-
# GB3. CR X LF
|
67
|
-
elsif previous == database.boundary[:cr] && current == database.boundary[:lf]
|
68
|
-
false
|
69
|
-
# GB4. (Control|CR|LF) ÷
|
70
|
-
elsif previous && in_char_class?(previous, [:control, :cr, :lf])
|
71
|
-
true
|
72
|
-
# GB5. ÷ (Control|CR|LF)
|
73
|
-
elsif in_char_class?(current, [:control, :cr, :lf])
|
74
|
-
true
|
75
|
-
# GB6. L X (L|V|LV|LVT)
|
76
|
-
elsif database.boundary[:l] === previous && in_char_class?(current, [:l, :v, :lv, :lvt])
|
77
|
-
false
|
78
|
-
# GB7. (LV|V) X (V|T)
|
79
|
-
elsif in_char_class?(previous, [:lv, :v]) && in_char_class?(current, [:v, :t])
|
80
|
-
false
|
81
|
-
# GB8. (LVT|T) X (T)
|
82
|
-
elsif in_char_class?(previous, [:lvt, :t]) && database.boundary[:t] === current
|
83
|
-
false
|
84
|
-
# GB9. X (Extend | ZWJ)
|
85
|
-
elsif in_char_class?(current, [:extend, :zwj])
|
86
|
-
false
|
87
|
-
# GB9a. X SpacingMark
|
88
|
-
elsif database.boundary[:spacingmark] === current
|
89
|
-
false
|
90
|
-
# GB9b. Prepend X
|
91
|
-
elsif database.boundary[:prepend] === previous
|
92
|
-
false
|
93
|
-
# GB10. (E_Base | EBG) Extend* X E_Modifier
|
94
|
-
elsif (marker...pos).any? { |i| in_char_class?(codepoints[i], [:e_base, :e_base_gaz]) && codepoints[i + 1...pos].all? { |c| database.boundary[:extend] === c } } && database.boundary[:e_modifier] === current
|
95
|
-
false
|
96
|
-
# GB11. ZWJ X (Glue_After_Zwj | EBG)
|
97
|
-
elsif database.boundary[:zwj] === previous && in_char_class?(current, [:glue_after_zwj, :e_base_gaz])
|
98
|
-
false
|
99
|
-
# GB12. ^ (RI RI)* RI X RI
|
100
|
-
# GB13. [^RI] (RI RI)* RI X RI
|
101
|
-
elsif codepoints[marker..pos].all? { |c| database.boundary[:regional_indicator] === c } && codepoints[marker..pos].count { |c| database.boundary[:regional_indicator] === c }.even?
|
102
|
-
false
|
103
|
-
# GB999. Any ÷ Any
|
104
|
-
else
|
105
|
-
true
|
106
|
-
end
|
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
|
107
41
|
|
108
|
-
|
109
|
-
unpacked << codepoints[marker..pos - 1]
|
110
|
-
marker = pos
|
111
|
-
end
|
112
|
-
end
|
113
|
-
unpacked
|
42
|
+
string.scan(/\X/).map(&:codepoints)
|
114
43
|
end
|
115
44
|
|
116
45
|
# Reverse operation of unpack_graphemes.
|
117
46
|
#
|
118
47
|
# Unicode.pack_graphemes(Unicode.unpack_graphemes('क्षि')) # => 'क्षि'
|
119
48
|
def pack_graphemes(unpacked)
|
120
|
-
|
121
|
-
|
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
|
122
53
|
|
123
|
-
|
124
|
-
def reorder_characters(codepoints)
|
125
|
-
length = codepoints.length - 1
|
126
|
-
pos = 0
|
127
|
-
while pos < length do
|
128
|
-
cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos + 1]]
|
129
|
-
if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
|
130
|
-
codepoints[pos..pos + 1] = cp2.code, cp1.code
|
131
|
-
pos += (pos > 0 ? -1 : 1)
|
132
|
-
else
|
133
|
-
pos += 1
|
134
|
-
end
|
135
|
-
end
|
136
|
-
codepoints
|
54
|
+
unpacked.flatten.pack("U*")
|
137
55
|
end
|
138
56
|
|
139
57
|
# Decompose composed characters to the decomposed form.
|
140
58
|
def decompose(type, codepoints)
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
ncp = [] # new codepoints
|
146
|
-
ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
|
147
|
-
ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
|
148
|
-
tindex = sindex % HANGUL_TCOUNT
|
149
|
-
ncp << (HANGUL_TBASE + tindex) unless tindex == 0
|
150
|
-
decomposed.concat ncp
|
151
|
-
# if the codepoint is decomposable in with the current decomposition type
|
152
|
-
elsif (ncp = database.codepoints[cp].decomp_mapping) && (!database.codepoints[cp].decomp_type || type == :compatibility)
|
153
|
-
decomposed.concat decompose(type, ncp.dup)
|
154
|
-
else
|
155
|
-
decomposed << cp
|
156
|
-
end
|
59
|
+
if type == :compatibility
|
60
|
+
codepoints.pack("U*").unicode_normalize(:nfkd).codepoints
|
61
|
+
else
|
62
|
+
codepoints.pack("U*").unicode_normalize(:nfd).codepoints
|
157
63
|
end
|
158
64
|
end
|
159
65
|
|
160
66
|
# Compose decomposed characters to the composed form.
|
161
67
|
def compose(codepoints)
|
162
|
-
|
163
|
-
eoa = codepoints.length - 1
|
164
|
-
starter_pos = 0
|
165
|
-
starter_char = codepoints[0]
|
166
|
-
previous_combining_class = -1
|
167
|
-
while pos < eoa
|
168
|
-
pos += 1
|
169
|
-
lindex = starter_char - HANGUL_LBASE
|
170
|
-
# -- Hangul
|
171
|
-
if 0 <= lindex && lindex < HANGUL_LCOUNT
|
172
|
-
vindex = codepoints[starter_pos + 1] - HANGUL_VBASE rescue vindex = -1
|
173
|
-
if 0 <= vindex && vindex < HANGUL_VCOUNT
|
174
|
-
tindex = codepoints[starter_pos + 2] - HANGUL_TBASE rescue tindex = -1
|
175
|
-
if 0 <= tindex && tindex < HANGUL_TCOUNT
|
176
|
-
j = starter_pos + 2
|
177
|
-
eoa -= 2
|
178
|
-
else
|
179
|
-
tindex = 0
|
180
|
-
j = starter_pos + 1
|
181
|
-
eoa -= 1
|
182
|
-
end
|
183
|
-
codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
|
184
|
-
end
|
185
|
-
starter_pos += 1
|
186
|
-
starter_char = codepoints[starter_pos]
|
187
|
-
# -- Other characters
|
188
|
-
else
|
189
|
-
current_char = codepoints[pos]
|
190
|
-
current = database.codepoints[current_char]
|
191
|
-
if current.combining_class > previous_combining_class
|
192
|
-
if ref = database.composition_map[starter_char]
|
193
|
-
composition = ref[current_char]
|
194
|
-
else
|
195
|
-
composition = nil
|
196
|
-
end
|
197
|
-
unless composition.nil?
|
198
|
-
codepoints[starter_pos] = composition
|
199
|
-
starter_char = composition
|
200
|
-
codepoints.delete_at pos
|
201
|
-
eoa -= 1
|
202
|
-
pos -= 1
|
203
|
-
previous_combining_class = -1
|
204
|
-
else
|
205
|
-
previous_combining_class = current.combining_class
|
206
|
-
end
|
207
|
-
else
|
208
|
-
previous_combining_class = current.combining_class
|
209
|
-
end
|
210
|
-
if current.combining_class == 0
|
211
|
-
starter_pos = pos
|
212
|
-
starter_char = codepoints[pos]
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
codepoints
|
68
|
+
codepoints.pack("U*").unicode_normalize(:nfc).codepoints
|
217
69
|
end
|
218
70
|
|
219
71
|
# Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
|
@@ -265,130 +117,41 @@ module ActiveSupport
|
|
265
117
|
# Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
|
266
118
|
def normalize(string, form = nil)
|
267
119
|
form ||= @default_normalization_form
|
268
|
-
# See http://www.unicode.org/reports/tr15, Table 1
|
269
|
-
codepoints = string.codepoints.to_a
|
270
|
-
case form
|
271
|
-
when :d
|
272
|
-
reorder_characters(decompose(:canonical, codepoints))
|
273
|
-
when :c
|
274
|
-
compose(reorder_characters(decompose(:canonical, codepoints)))
|
275
|
-
when :kd
|
276
|
-
reorder_characters(decompose(:compatibility, codepoints))
|
277
|
-
when :kc
|
278
|
-
compose(reorder_characters(decompose(:compatibility, codepoints)))
|
279
|
-
else
|
280
|
-
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
281
|
-
end.pack("U*".freeze)
|
282
|
-
end
|
283
|
-
|
284
|
-
def downcase(string)
|
285
|
-
apply_mapping string, :lowercase_mapping
|
286
|
-
end
|
287
120
|
|
288
|
-
|
289
|
-
|
290
|
-
|
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
|
291
127
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping
|
299
|
-
|
300
|
-
# Initializing Codepoint object with default values
|
301
|
-
def initialize
|
302
|
-
@combining_class = 0
|
303
|
-
@uppercase_mapping = 0
|
304
|
-
@lowercase_mapping = 0
|
305
|
-
end
|
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
|
306
134
|
|
307
|
-
|
308
|
-
uppercase_mapping > 0 ? uppercase_mapping : lowercase_mapping
|
135
|
+
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
309
136
|
end
|
310
137
|
end
|
311
138
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
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
|
317
145
|
|
318
|
-
|
319
|
-
@codepoints = Hash.new(Codepoint.new)
|
320
|
-
@composition_exclusion = []
|
321
|
-
@composition_map = {}
|
322
|
-
@boundary = {}
|
323
|
-
@cp1252 = {}
|
324
|
-
end
|
325
|
-
|
326
|
-
# Lazy load the Unicode database so it's only loaded when it's actually used
|
327
|
-
ATTRIBUTES.each do |attr_name|
|
328
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
329
|
-
def #{attr_name} # def codepoints
|
330
|
-
load # load
|
331
|
-
@#{attr_name} # @codepoints
|
332
|
-
end # end
|
333
|
-
EOS
|
334
|
-
end
|
335
|
-
|
336
|
-
# Loads the Unicode database and returns all the internal objects of
|
337
|
-
# UnicodeDatabase.
|
338
|
-
def load
|
339
|
-
begin
|
340
|
-
@codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, "rb") { |f| Marshal.load f.read }
|
341
|
-
rescue => e
|
342
|
-
raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), ActiveSupport::Multibyte is unusable")
|
343
|
-
end
|
344
|
-
|
345
|
-
# Redefine the === method so we can write shorter rules for grapheme cluster breaks
|
346
|
-
@boundary.each_key do |k|
|
347
|
-
@boundary[k].instance_eval do
|
348
|
-
def ===(other)
|
349
|
-
detect { |i| i === other } ? true : false
|
350
|
-
end
|
351
|
-
end if @boundary[k].kind_of?(Array)
|
352
|
-
end
|
353
|
-
|
354
|
-
# define attr_reader methods for the instance variables
|
355
|
-
class << self
|
356
|
-
attr_reader(*ATTRIBUTES)
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
# Returns the directory in which the data files are stored.
|
361
|
-
def self.dirname
|
362
|
-
File.expand_path("../values", __dir__)
|
363
|
-
end
|
364
|
-
|
365
|
-
# Returns the filename for the data file for this version.
|
366
|
-
def self.filename
|
367
|
-
File.expand_path File.join(dirname, "unicode_tables.dat")
|
146
|
+
string.send(method)
|
368
147
|
end
|
369
148
|
end
|
370
149
|
|
371
150
|
private
|
372
151
|
|
373
|
-
def apply_mapping(string, mapping)
|
374
|
-
database.codepoints
|
375
|
-
string.each_codepoint.map do |codepoint|
|
376
|
-
cp = database.codepoints[codepoint]
|
377
|
-
if cp && (ncp = cp.send(mapping)) && ncp > 0
|
378
|
-
ncp
|
379
|
-
else
|
380
|
-
codepoint
|
381
|
-
end
|
382
|
-
end.pack("U*")
|
383
|
-
end
|
384
|
-
|
385
152
|
def recode_windows1252_chars(string)
|
386
153
|
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
387
154
|
end
|
388
|
-
|
389
|
-
def database
|
390
|
-
@database ||= UnicodeDatabase.new
|
391
|
-
end
|
392
155
|
end
|
393
156
|
end
|
394
157
|
end
|
@@ -34,7 +34,7 @@ module ActiveSupport
|
|
34
34
|
# name # => String, name of the event (such as 'render' from above)
|
35
35
|
# start # => Time, when the instrumented block started execution
|
36
36
|
# finish # => Time, when the instrumented block ended execution
|
37
|
-
# id # => String, unique ID for
|
37
|
+
# id # => String, unique ID for the instrumenter that fired the event
|
38
38
|
# payload # => Hash, the payload
|
39
39
|
# end
|
40
40
|
#
|
@@ -59,7 +59,7 @@ module ActiveSupport
|
|
59
59
|
# event.payload # => { extra: :information }
|
60
60
|
#
|
61
61
|
# The block in the <tt>subscribe</tt> call gets the name of the event, start
|
62
|
-
# timestamp, end timestamp, a string with a unique identifier for that event
|
62
|
+
# timestamp, end timestamp, a string with a unique identifier for that event's instrumenter
|
63
63
|
# (something like "535801666f04d0298cd6"), and a hash with the payload, in
|
64
64
|
# that order.
|
65
65
|
#
|
@@ -67,9 +67,12 @@ module ActiveSupport
|
|
67
67
|
# have a key <tt>:exception</tt> with an array of two elements as value: a string with
|
68
68
|
# the name of the exception class, and the exception message.
|
69
69
|
# The <tt>:exception_object</tt> key of the payload will have the exception
|
70
|
-
# itself as the value
|
70
|
+
# itself as the value:
|
71
71
|
#
|
72
|
-
#
|
72
|
+
# event.payload[:exception] # => ["ArgumentError", "Invalid value"]
|
73
|
+
# event.payload[:exception_object] # => #<ArgumentError: Invalid value>
|
74
|
+
#
|
75
|
+
# As the earlier example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
|
73
76
|
# is able to take the arguments as they come and provide an object-oriented
|
74
77
|
# interface to that data.
|
75
78
|
#
|
@@ -150,6 +153,15 @@ module ActiveSupport
|
|
150
153
|
#
|
151
154
|
# ActiveSupport::Notifications.unsubscribe("render")
|
152
155
|
#
|
156
|
+
# Subscribers using a regexp or other pattern-matching object will remain subscribed
|
157
|
+
# to all events that match their original pattern, unless those events match a string
|
158
|
+
# passed to `unsubscribe`:
|
159
|
+
#
|
160
|
+
# subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
|
161
|
+
# ActiveSupport::Notifications.unsubscribe('render_template.action_view')
|
162
|
+
# subscriber.matches?('render_template.action_view') # => false
|
163
|
+
# subscriber.matches?('render_partial.action_view') # => true
|
164
|
+
#
|
153
165
|
# == Default Queue
|
154
166
|
#
|
155
167
|
# Notifications ships with a queue implementation that consumes and publishes events
|
@@ -171,6 +183,31 @@ module ActiveSupport
|
|
171
183
|
end
|
172
184
|
end
|
173
185
|
|
186
|
+
# Subscribe to a given event name with the passed +block+.
|
187
|
+
#
|
188
|
+
# You can subscribe to events by passing a String to match exact event
|
189
|
+
# names, or by passing a Regexp to match all events that match a pattern.
|
190
|
+
#
|
191
|
+
# ActiveSupport::Notifications.subscribe(/render/) do |*args|
|
192
|
+
# @event = ActiveSupport::Notifications::Event.new(*args)
|
193
|
+
# end
|
194
|
+
#
|
195
|
+
# The +block+ will receive five parameters with information about the event:
|
196
|
+
#
|
197
|
+
# ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
|
198
|
+
# name # => String, name of the event (such as 'render' from above)
|
199
|
+
# start # => Time, when the instrumented block started execution
|
200
|
+
# finish # => Time, when the instrumented block ended execution
|
201
|
+
# id # => String, unique ID for the instrumenter that fired the event
|
202
|
+
# payload # => Hash, the payload
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# If the block passed to the method only takes one parameter,
|
206
|
+
# it will yield an event object to the block:
|
207
|
+
#
|
208
|
+
# ActiveSupport::Notifications.subscribe(/render/) do |event|
|
209
|
+
# @event = event
|
210
|
+
# end
|
174
211
|
def subscribe(*args, &block)
|
175
212
|
notifier.subscribe(*args, &block)
|
176
213
|
end
|