activesupport 5.2.7.1 → 6.1.4.6
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 +399 -434
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +29 -3
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +34 -34
- data/lib/active_support/cache/mem_cache_store.rb +39 -24
- data/lib/active_support/cache/memory_store.rb +59 -33
- data/lib/active_support/cache/null_store.rb +8 -3
- data/lib/active_support/cache/redis_cache_store.rb +72 -45
- data/lib/active_support/cache/strategy/local_cache.rb +41 -26
- data/lib/active_support/cache.rb +148 -78
- data/lib/active_support/callbacks.rb +81 -64
- data/lib/active_support/concern.rb +70 -3
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/configurable.rb +10 -14
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/array/conversions.rb +5 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array.rb +1 -1
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +32 -47
- data/lib/active_support/core_ext/class/subclasses.rb +17 -38
- data/lib/active_support/core_ext/date/calculations.rb +6 -5
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
- data/lib/active_support/core_ext/enumerable.rb +171 -75
- data/lib/active_support/core_ext/hash/conversions.rb +3 -3
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +2 -2
- data/lib/active_support/core_ext/hash/keys.rb +1 -30
- data/lib/active_support/core_ext/hash/slice.rb +6 -27
- data/lib/active_support/core_ext/hash.rb +1 -2
- 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/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 +30 -39
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +76 -33
- data/lib/active_support/core_ext/module/introspection.rb +16 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/name_error.rb +29 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/blank.rb +1 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +7 -114
- data/lib/active_support/core_ext/object/json.rb +14 -2
- data/lib/active_support/core_ext/object/try.rb +17 -7
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/compare_range.rb +34 -13
- data/lib/active_support/core_ext/range/conversions.rb +31 -29
- data/lib/active_support/core_ext/range/each.rb +0 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
- data/lib/active_support/core_ext/regexp.rb +8 -5
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +5 -16
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/filters.rb +42 -1
- data/lib/active_support/core_ext/string/inflections.rb +45 -6
- data/lib/active_support/core_ext/string/inquiry.rb +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +6 -5
- data/lib/active_support/core_ext/string/output_safety.rb +70 -41
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- 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 +51 -3
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +6 -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 +16 -2
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +109 -34
- data/lib/active_support/deprecation/behaviors.rb +16 -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 +18 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/descendants_tracker.rb +59 -9
- data/lib/active_support/duration/iso8601_parser.rb +2 -4
- data/lib/active_support/duration/iso8601_serializer.rb +18 -14
- data/lib/active_support/duration.rb +78 -30
- data/lib/active_support/encrypted_configuration.rb +0 -4
- data/lib/active_support/encrypted_file.rb +22 -4
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +82 -117
- data/lib/active_support/execution_wrapper.rb +2 -1
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +70 -42
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +15 -8
- data/lib/active_support/inflector/inflections.rb +2 -7
- data/lib/active_support/inflector/methods.rb +49 -58
- data/lib/active_support/inflector/transliterate.rb +47 -18
- data/lib/active_support/json/decoding.rb +25 -26
- data/lib/active_support/json/encoding.rb +11 -3
- data/lib/active_support/key_generator.rb +1 -33
- data/lib/active_support/lazy_load_hooks.rb +5 -2
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber.rb +39 -9
- data/lib/active_support/logger.rb +2 -17
- data/lib/active_support/logger_silence.rb +11 -19
- data/lib/active_support/logger_thread_safe_level.rb +50 -6
- data/lib/active_support/message_encryptor.rb +8 -13
- data/lib/active_support/message_verifier.rb +10 -10
- data/lib/active_support/messages/metadata.rb +11 -2
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +10 -9
- data/lib/active_support/multibyte/chars.rb +10 -68
- data/lib/active_support/multibyte/unicode.rb +15 -327
- data/lib/active_support/notifications/fanout.rb +116 -16
- data/lib/active_support/notifications/instrumenter.rb +71 -9
- data/lib/active_support/notifications.rb +72 -8
- data/lib/active_support/number_helper/number_converter.rb +5 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
- 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 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -7
- data/lib/active_support/number_helper/rounding_helper.rb +12 -28
- data/lib/active_support/number_helper.rb +38 -12
- data/lib/active_support/option_merger.rb +22 -3
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +13 -3
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +1 -1
- data/lib/active_support/rails.rb +1 -10
- data/lib/active_support/railtie.rb +23 -1
- data/lib/active_support/reloader.rb +4 -5
- 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 -3
- data/lib/active_support/subscriber.rb +72 -28
- data/lib/active_support/tagged_logging.rb +42 -8
- data/lib/active_support/test_case.rb +91 -0
- data/lib/active_support/testing/assertions.rb +30 -9
- 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/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/stream.rb +1 -2
- data/lib/active_support/testing/time_helpers.rb +47 -12
- data/lib/active_support/time_with_zone.rb +81 -47
- data/lib/active_support/values/time_zone.rb +32 -17
- data/lib/active_support/xml_mini/jdom.rb +2 -3
- 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 +10 -3
- data/lib/active_support/xml_mini.rb +2 -10
- data/lib/active_support.rb +14 -1
- metadata +55 -29
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
- data/lib/active_support/core_ext/hash/compact.rb +0 -29
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/core_ext/module/reachable.rb +0 -11
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
- data/lib/active_support/core_ext/range/include_range.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,10 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "concurrent/map"
|
4
|
-
require "active_support/core_ext/array/prepend_and_append"
|
5
|
-
require "active_support/core_ext/regexp"
|
6
4
|
require "active_support/i18n"
|
7
|
-
require "active_support/deprecation"
|
8
5
|
|
9
6
|
module ActiveSupport
|
10
7
|
module Inflector
|
@@ -67,8 +64,7 @@ module ActiveSupport
|
|
67
64
|
@__instance__[locale] ||= new
|
68
65
|
end
|
69
66
|
|
70
|
-
attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms
|
71
|
-
deprecate :acronym_regex
|
67
|
+
attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms
|
72
68
|
|
73
69
|
attr_reader :acronyms_camelize_regex, :acronyms_underscore_regex # :nodoc:
|
74
70
|
|
@@ -80,7 +76,7 @@ module ActiveSupport
|
|
80
76
|
# Private, for the test suite.
|
81
77
|
def initialize_dup(orig) # :nodoc:
|
82
78
|
%w(plurals singulars uncountables humans acronyms).each do |scope|
|
83
|
-
instance_variable_set("@#{scope}", orig.
|
79
|
+
instance_variable_set("@#{scope}", orig.public_send(scope).dup)
|
84
80
|
end
|
85
81
|
define_acronym_regex_patterns
|
86
82
|
end
|
@@ -233,7 +229,6 @@ module ActiveSupport
|
|
233
229
|
end
|
234
230
|
|
235
231
|
private
|
236
|
-
|
237
232
|
def define_acronym_regex_patterns
|
238
233
|
@acronym_regex = @acronyms.empty? ? /(?=a)b/ : /#{@acronyms.values.join("|")}/
|
239
234
|
@acronyms_camelize_regex = /^(?:#{@acronym_regex}(?=\b|[A-Z_])|\w)/
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/inflections"
|
4
|
-
require "active_support/core_ext/
|
4
|
+
require "active_support/core_ext/object/blank"
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
7
|
# The Inflector transforms words from singular to plural, class names to table
|
@@ -74,7 +74,7 @@ module ActiveSupport
|
|
74
74
|
string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase }
|
75
75
|
end
|
76
76
|
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
|
77
|
-
string.gsub!("/"
|
77
|
+
string.gsub!("/", "::")
|
78
78
|
string
|
79
79
|
end
|
80
80
|
|
@@ -91,11 +91,11 @@ module ActiveSupport
|
|
91
91
|
# camelize(underscore('SSLError')) # => "SslError"
|
92
92
|
def underscore(camel_cased_word)
|
93
93
|
return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
|
94
|
-
word = camel_cased_word.to_s.gsub("::"
|
95
|
-
word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_'
|
96
|
-
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'
|
97
|
-
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'
|
98
|
-
word.tr!("-"
|
94
|
+
word = camel_cased_word.to_s.gsub("::", "/")
|
95
|
+
word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
|
96
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
97
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
98
|
+
word.tr!("-", "_")
|
99
99
|
word.downcase!
|
100
100
|
word
|
101
101
|
end
|
@@ -131,11 +131,11 @@ module ActiveSupport
|
|
131
131
|
|
132
132
|
inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
133
133
|
|
134
|
-
result.sub!(/\A_+/, ""
|
134
|
+
result.sub!(/\A_+/, "")
|
135
135
|
unless keep_id_suffix
|
136
|
-
result.
|
136
|
+
result.delete_suffix!("_id")
|
137
137
|
end
|
138
|
-
result.tr!("_"
|
138
|
+
result.tr!("_", " ")
|
139
139
|
|
140
140
|
result.gsub!(/([a-z\d]*)/i) do |match|
|
141
141
|
"#{inflections.acronyms[match.downcase] || match.downcase}"
|
@@ -173,7 +173,7 @@ module ActiveSupport
|
|
173
173
|
# titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
|
174
174
|
# titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
|
175
175
|
def titleize(word, keep_id_suffix: false)
|
176
|
-
humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`])[a-z]/) do |match|
|
176
|
+
humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`()])[a-z]/) do |match|
|
177
177
|
match.capitalize
|
178
178
|
end
|
179
179
|
end
|
@@ -197,17 +197,17 @@ module ActiveSupport
|
|
197
197
|
#
|
198
198
|
# Singular names are not handled correctly:
|
199
199
|
#
|
200
|
-
# classify('calculus') # => "
|
200
|
+
# classify('calculus') # => "Calculu"
|
201
201
|
def classify(table_name)
|
202
202
|
# strip out any leading schema name
|
203
|
-
camelize(singularize(table_name.to_s.sub(/.*\./, ""
|
203
|
+
camelize(singularize(table_name.to_s.sub(/.*\./, "")))
|
204
204
|
end
|
205
205
|
|
206
206
|
# Replaces underscores with dashes in the string.
|
207
207
|
#
|
208
208
|
# dasherize('puni_puni') # => "puni-puni"
|
209
209
|
def dasherize(underscored_word)
|
210
|
-
underscored_word.tr("_"
|
210
|
+
underscored_word.tr("_", "-")
|
211
211
|
end
|
212
212
|
|
213
213
|
# Removes the module part from the expression in the string.
|
@@ -270,32 +270,36 @@ module ActiveSupport
|
|
270
270
|
# NameError is raised when the name is not in CamelCase or the constant is
|
271
271
|
# unknown.
|
272
272
|
def constantize(camel_cased_word)
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
if
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
const
|
273
|
+
if camel_cased_word.blank? || !camel_cased_word.include?("::")
|
274
|
+
Object.const_get(camel_cased_word)
|
275
|
+
else
|
276
|
+
names = camel_cased_word.split("::")
|
277
|
+
|
278
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
279
|
+
Object.const_get(camel_cased_word) if names.empty?
|
280
|
+
|
281
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
282
|
+
names.shift if names.size > 1 && names.first.empty?
|
283
|
+
|
284
|
+
names.inject(Object) do |constant, name|
|
285
|
+
if constant == Object
|
286
|
+
constant.const_get(name)
|
287
|
+
else
|
288
|
+
candidate = constant.const_get(name)
|
289
|
+
next candidate if constant.const_defined?(name, false)
|
290
|
+
next candidate unless Object.const_defined?(name)
|
291
|
+
|
292
|
+
# Go down the ancestors to check if it is owned directly. The check
|
293
|
+
# stops when we reach Object or the end of ancestors tree.
|
294
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
295
|
+
break const if ancestor == Object
|
296
|
+
break ancestor if ancestor.const_defined?(name, false)
|
297
|
+
const
|
298
|
+
end
|
299
|
+
|
300
|
+
# owner is in Object, so raise
|
301
|
+
constant.const_get(name, false)
|
295
302
|
end
|
296
|
-
|
297
|
-
# owner is in Object, so raise
|
298
|
-
constant.const_get(name, false)
|
299
303
|
end
|
300
304
|
end
|
301
305
|
end
|
@@ -327,10 +331,9 @@ module ActiveSupport
|
|
327
331
|
rescue NameError => e
|
328
332
|
raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
|
329
333
|
e.name.to_s == camel_cased_word.to_s)
|
330
|
-
rescue ArgumentError => e
|
331
|
-
raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message)
|
332
334
|
rescue LoadError => e
|
333
|
-
|
335
|
+
message = e.respond_to?(:original_message) ? e.original_message : e.message
|
336
|
+
raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(message)
|
334
337
|
end
|
335
338
|
|
336
339
|
# Returns the suffix that should be added to a number to denote the position
|
@@ -343,18 +346,7 @@ module ActiveSupport
|
|
343
346
|
# ordinal(-11) # => "th"
|
344
347
|
# ordinal(-1021) # => "st"
|
345
348
|
def ordinal(number)
|
346
|
-
|
347
|
-
|
348
|
-
if (11..13).include?(abs_number % 100)
|
349
|
-
"th"
|
350
|
-
else
|
351
|
-
case abs_number % 10
|
352
|
-
when 1; "st"
|
353
|
-
when 2; "nd"
|
354
|
-
when 3; "rd"
|
355
|
-
else "th"
|
356
|
-
end
|
357
|
-
end
|
349
|
+
I18n.translate("number.nth.ordinals", number: number)
|
358
350
|
end
|
359
351
|
|
360
352
|
# Turns a number into an ordinal string used to denote the position in an
|
@@ -367,24 +359,23 @@ module ActiveSupport
|
|
367
359
|
# ordinalize(-11) # => "-11th"
|
368
360
|
# ordinalize(-1021) # => "-1021st"
|
369
361
|
def ordinalize(number)
|
370
|
-
"
|
362
|
+
I18n.translate("number.nth.ordinalized", number: number)
|
371
363
|
end
|
372
364
|
|
373
365
|
private
|
374
|
-
|
375
366
|
# Mounts a regular expression, returned as a string to ease interpolation,
|
376
367
|
# that will match part by part the given constant.
|
377
368
|
#
|
378
369
|
# const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
|
379
370
|
# const_regexp("::") # => "::"
|
380
371
|
def const_regexp(camel_cased_word)
|
381
|
-
parts = camel_cased_word.split("::"
|
372
|
+
parts = camel_cased_word.split("::")
|
382
373
|
|
383
374
|
return Regexp.escape(camel_cased_word) if parts.blank?
|
384
375
|
|
385
376
|
last = parts.pop
|
386
377
|
|
387
|
-
parts.reverse
|
378
|
+
parts.reverse!.inject(last) do |acc, part|
|
388
379
|
part.empty? ? acc : "#{part}(::#{acc})?"
|
389
380
|
end
|
390
381
|
end
|
@@ -5,6 +5,8 @@ require "active_support/i18n"
|
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
7
|
module Inflector
|
8
|
+
ALLOWED_ENCODINGS_FOR_TRANSLITERATE = [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030].freeze
|
9
|
+
|
8
10
|
# Replaces non-ASCII characters with an ASCII approximation, or if none
|
9
11
|
# exists, a replacement character which defaults to "?".
|
10
12
|
#
|
@@ -51,20 +53,43 @@ module ActiveSupport
|
|
51
53
|
#
|
52
54
|
# Now you can have different transliterations for each locale:
|
53
55
|
#
|
54
|
-
#
|
55
|
-
# transliterate('Jürgen')
|
56
|
+
# transliterate('Jürgen', locale: :en)
|
56
57
|
# # => "Jurgen"
|
57
58
|
#
|
58
|
-
#
|
59
|
-
# transliterate('Jürgen')
|
59
|
+
# transliterate('Jürgen', locale: :de)
|
60
60
|
# # => "Juergen"
|
61
|
-
|
61
|
+
#
|
62
|
+
# Transliteration is restricted to UTF-8, US-ASCII and GB18030 strings
|
63
|
+
# Other encodings will raise an ArgumentError.
|
64
|
+
def transliterate(string, replacement = "?", locale: nil)
|
65
|
+
string = string.dup if string.frozen?
|
62
66
|
raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
|
67
|
+
raise ArgumentError, "Cannot transliterate strings with #{string.encoding} encoding" unless ALLOWED_ENCODINGS_FOR_TRANSLITERATE.include?(string.encoding)
|
68
|
+
|
69
|
+
input_encoding = string.encoding
|
70
|
+
|
71
|
+
# US-ASCII is a subset of UTF-8 so we'll force encoding as UTF-8 if
|
72
|
+
# US-ASCII is given. This way we can let tidy_bytes handle the string
|
73
|
+
# in the same way as we do for UTF-8
|
74
|
+
string.force_encoding(Encoding::UTF_8) if string.encoding == Encoding::US_ASCII
|
75
|
+
|
76
|
+
# GB18030 is Unicode compatible but is not a direct mapping so needs to be
|
77
|
+
# transcoded. Using invalid/undef :replace will result in loss of data in
|
78
|
+
# the event of invalid characters, but since tidy_bytes will replace
|
79
|
+
# invalid/undef with a "?" we're safe to do the same beforehand
|
80
|
+
string.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) if string.encoding == Encoding::GB18030
|
81
|
+
|
82
|
+
transliterated = I18n.transliterate(
|
83
|
+
ActiveSupport::Multibyte::Unicode.tidy_bytes(string).unicode_normalize(:nfc),
|
84
|
+
replacement: replacement,
|
85
|
+
locale: locale
|
86
|
+
)
|
87
|
+
|
88
|
+
# Restore the string encoding of the input if it was not UTF-8.
|
89
|
+
# Apply invalid/undef :replace as tidy_bytes does
|
90
|
+
transliterated.encode!(input_encoding, invalid: :replace, undef: :replace) if input_encoding != transliterated.encoding
|
63
91
|
|
64
|
-
|
65
|
-
ActiveSupport::Multibyte::Unicode.normalize(
|
66
|
-
ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
|
67
|
-
replacement: replacement)
|
92
|
+
transliterated
|
68
93
|
end
|
69
94
|
|
70
95
|
# Replaces special characters in a string so that it may be used as part of
|
@@ -75,8 +100,8 @@ module ActiveSupport
|
|
75
100
|
#
|
76
101
|
# To use a custom separator, override the +separator+ argument.
|
77
102
|
#
|
78
|
-
#
|
79
|
-
#
|
103
|
+
# parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
|
104
|
+
# parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie"
|
80
105
|
#
|
81
106
|
# To preserve the case of the characters in a string, use the +preserve_case+ argument.
|
82
107
|
#
|
@@ -85,19 +110,23 @@ module ActiveSupport
|
|
85
110
|
#
|
86
111
|
# It preserves dashes and underscores unless they are used as separators:
|
87
112
|
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
113
|
+
# parameterize("^très|Jolie__ ") # => "tres-jolie__"
|
114
|
+
# parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
|
115
|
+
# parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
|
91
116
|
#
|
92
|
-
|
117
|
+
# If the optional parameter +locale+ is specified,
|
118
|
+
# the word will be parameterized as a word of that language.
|
119
|
+
# By default, this parameter is set to <tt>nil</tt> and it will use
|
120
|
+
# the configured <tt>I18n.locale</tt>.
|
121
|
+
def parameterize(string, separator: "-", preserve_case: false, locale: nil)
|
93
122
|
# Replace accented chars with their ASCII equivalents.
|
94
|
-
parameterized_string = transliterate(string)
|
123
|
+
parameterized_string = transliterate(string, locale: locale)
|
95
124
|
|
96
125
|
# Turn unwanted chars into the separator.
|
97
126
|
parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
|
98
127
|
|
99
128
|
unless separator.nil? || separator.empty?
|
100
|
-
if separator == "-"
|
129
|
+
if separator == "-"
|
101
130
|
re_duplicate_separator = /-{2,}/
|
102
131
|
re_leading_trailing_separator = /^-|-$/i
|
103
132
|
else
|
@@ -108,7 +137,7 @@ module ActiveSupport
|
|
108
137
|
# No more than one of the separator in a row.
|
109
138
|
parameterized_string.gsub!(re_duplicate_separator, separator)
|
110
139
|
# Remove leading/trailing separator.
|
111
|
-
parameterized_string.gsub!(re_leading_trailing_separator, ""
|
140
|
+
parameterized_string.gsub!(re_leading_trailing_separator, "")
|
112
141
|
end
|
113
142
|
|
114
143
|
parameterized_string.downcase! unless preserve_case
|
@@ -10,8 +10,8 @@ module ActiveSupport
|
|
10
10
|
|
11
11
|
module JSON
|
12
12
|
# matches YAML-formatted dates
|
13
|
-
DATE_REGEX =
|
14
|
-
DATETIME_REGEX =
|
13
|
+
DATE_REGEX = /\A\d{4}-\d{2}-\d{2}\z/
|
14
|
+
DATETIME_REGEX = /\A(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)\z/
|
15
15
|
|
16
16
|
class << self
|
17
17
|
# Parses a JSON string (JavaScript Object Notation) into a hash.
|
@@ -44,33 +44,32 @@ module ActiveSupport
|
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
47
|
+
def convert_dates_from(data)
|
48
|
+
case data
|
49
|
+
when nil
|
50
|
+
nil
|
51
|
+
when DATE_REGEX
|
52
|
+
begin
|
53
|
+
Date.parse(data)
|
54
|
+
rescue ArgumentError
|
55
|
+
data
|
56
|
+
end
|
57
|
+
when DATETIME_REGEX
|
58
|
+
begin
|
59
|
+
Time.zone.parse(data)
|
60
|
+
rescue ArgumentError
|
61
|
+
data
|
62
|
+
end
|
63
|
+
when Array
|
64
|
+
data.map! { |d| convert_dates_from(d) }
|
65
|
+
when Hash
|
66
|
+
data.transform_values! do |value|
|
67
|
+
convert_dates_from(value)
|
68
|
+
end
|
69
|
+
else
|
62
70
|
data
|
63
71
|
end
|
64
|
-
when Array
|
65
|
-
data.map! { |d| convert_dates_from(d) }
|
66
|
-
when Hash
|
67
|
-
data.each do |key, value|
|
68
|
-
data[key] = convert_dates_from(value)
|
69
|
-
end
|
70
|
-
else
|
71
|
-
data
|
72
72
|
end
|
73
|
-
end
|
74
73
|
end
|
75
74
|
end
|
76
75
|
end
|
@@ -54,9 +54,13 @@ module ActiveSupport
|
|
54
54
|
class EscapedString < String #:nodoc:
|
55
55
|
def to_json(*)
|
56
56
|
if Encoding.escape_html_entities_in_json
|
57
|
-
|
57
|
+
s = super
|
58
|
+
s.gsub! ESCAPE_REGEX_WITH_HTML_ENTITIES, ESCAPED_CHARS
|
59
|
+
s
|
58
60
|
else
|
59
|
-
|
61
|
+
s = super
|
62
|
+
s.gsub! ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, ESCAPED_CHARS
|
63
|
+
s
|
60
64
|
end
|
61
65
|
end
|
62
66
|
|
@@ -89,7 +93,11 @@ module ActiveSupport
|
|
89
93
|
when Numeric, NilClass, TrueClass, FalseClass
|
90
94
|
value.as_json
|
91
95
|
when Hash
|
92
|
-
|
96
|
+
result = {}
|
97
|
+
value.each do |k, v|
|
98
|
+
result[jsonify(k)] = jsonify(v)
|
99
|
+
end
|
100
|
+
result
|
93
101
|
when Array
|
94
102
|
value.map { |v| jsonify(v) }
|
95
103
|
else
|
@@ -35,39 +35,7 @@ module ActiveSupport
|
|
35
35
|
|
36
36
|
# Returns a derived key suitable for use.
|
37
37
|
def generate_key(*args)
|
38
|
-
@cache_keys[args.join] ||= @key_generator.generate_key(*args)
|
38
|
+
@cache_keys[args.join("|")] ||= @key_generator.generate_key(*args)
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
42
|
-
class LegacyKeyGenerator # :nodoc:
|
43
|
-
SECRET_MIN_LENGTH = 30 # Characters
|
44
|
-
|
45
|
-
def initialize(secret)
|
46
|
-
ensure_secret_secure(secret)
|
47
|
-
@secret = secret
|
48
|
-
end
|
49
|
-
|
50
|
-
def generate_key(salt)
|
51
|
-
@secret
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
# To prevent users from using something insecure like "Password" we make sure that the
|
57
|
-
# secret they've provided is at least 30 characters in length.
|
58
|
-
def ensure_secret_secure(secret)
|
59
|
-
if secret.blank?
|
60
|
-
raise ArgumentError, "A secret is required to generate an integrity hash " \
|
61
|
-
"for cookie session data. Set a secret_key_base of at least " \
|
62
|
-
"#{SECRET_MIN_LENGTH} characters in via `bin/rails credentials:edit`."
|
63
|
-
end
|
64
|
-
|
65
|
-
if secret.length < SECRET_MIN_LENGTH
|
66
|
-
raise ArgumentError, "Secret should be something secure, " \
|
67
|
-
"like \"#{SecureRandom.hex(16)}\". The value you " \
|
68
|
-
"provided, \"#{secret}\", is shorter than the minimum length " \
|
69
|
-
"of #{SECRET_MIN_LENGTH} characters."
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
41
|
end
|
@@ -54,7 +54,6 @@ module ActiveSupport
|
|
54
54
|
end
|
55
55
|
|
56
56
|
private
|
57
|
-
|
58
57
|
def with_execution_control(name, block, once)
|
59
58
|
unless @run_once[name].include?(block)
|
60
59
|
@run_once[name] << block if once
|
@@ -68,7 +67,11 @@ module ActiveSupport
|
|
68
67
|
if options[:yield]
|
69
68
|
block.call(base)
|
70
69
|
else
|
71
|
-
base.
|
70
|
+
if base.is_a?(Module)
|
71
|
+
base.class_eval(&block)
|
72
|
+
else
|
73
|
+
base.instance_eval(&block)
|
74
|
+
end
|
72
75
|
end
|
73
76
|
end
|
74
77
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
{
|
4
|
+
en: {
|
5
|
+
number: {
|
6
|
+
nth: {
|
7
|
+
ordinals: lambda do |_key, options|
|
8
|
+
number = options[:number]
|
9
|
+
case number
|
10
|
+
when 1; "st"
|
11
|
+
when 2; "nd"
|
12
|
+
when 3; "rd"
|
13
|
+
when 4, 5, 6, 7, 8, 9, 10, 11, 12, 13; "th"
|
14
|
+
else
|
15
|
+
num_modulo = number.to_i.abs % 100
|
16
|
+
num_modulo %= 10 if num_modulo > 13
|
17
|
+
case num_modulo
|
18
|
+
when 1; "st"
|
19
|
+
when 2; "nd"
|
20
|
+
when 3; "rd"
|
21
|
+
else "th"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end,
|
25
|
+
|
26
|
+
ordinalized: lambda do |_key, options|
|
27
|
+
number = options[:number]
|
28
|
+
"#{number}#{ActiveSupport::Inflector.ordinal(number)}"
|
29
|
+
end
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
@@ -44,10 +44,12 @@ en:
|
|
44
44
|
delimiter: ","
|
45
45
|
# Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
|
46
46
|
precision: 3
|
47
|
+
# Determine how rounding is performed (see BigDecimal::mode)
|
48
|
+
round_mode: default
|
47
49
|
# If set to true, precision will mean the number of significant digits instead
|
48
50
|
# of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
|
49
51
|
significant: false
|
50
|
-
# If set, the zeros after the decimal separator will always be stripped (
|
52
|
+
# If set, the zeros after the decimal separator will always be stripped (e.g.: 1.200 will be 1.2)
|
51
53
|
strip_insignificant_zeros: false
|
52
54
|
|
53
55
|
# Used in NumberHelper.number_to_currency()
|
@@ -56,10 +58,11 @@ en:
|
|
56
58
|
# Where is the currency sign? %u is the currency unit, %n the number (default: $5.00)
|
57
59
|
format: "%u%n"
|
58
60
|
unit: "$"
|
59
|
-
# These
|
61
|
+
# These six are to override number.format and are optional
|
60
62
|
separator: "."
|
61
63
|
delimiter: ","
|
62
64
|
precision: 2
|
65
|
+
# round_mode:
|
63
66
|
significant: false
|
64
67
|
strip_insignificant_zeros: false
|
65
68
|
|
@@ -87,10 +90,11 @@ en:
|
|
87
90
|
# Used in NumberHelper.number_to_human_size() and NumberHelper.number_to_human()
|
88
91
|
human:
|
89
92
|
format:
|
90
|
-
# These
|
93
|
+
# These six are to override number.format and are optional
|
91
94
|
# separator:
|
92
95
|
delimiter: ""
|
93
96
|
precision: 3
|
97
|
+
# round_mode:
|
94
98
|
significant: true
|
95
99
|
strip_insignificant_zeros: true
|
96
100
|
# Used in number_to_human_size()
|
@@ -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,39 @@ module ActiveSupport
|
|
29
29
|
# subscriber, the line above should be called after your
|
30
30
|
# <tt>ActiveRecord::LogSubscriber</tt> definition.
|
31
31
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
32
|
+
# A logger also needs to be set with <tt>ActiveRecord::LogSubscriber.logger=</tt>.
|
33
|
+
# This is assigned automatically in a Rails environment.
|
34
|
+
#
|
35
|
+
# After configured, whenever a <tt>"sql.active_record"</tt> notification is published,
|
36
|
+
# it will properly dispatch the event
|
37
|
+
# (<tt>ActiveSupport::Notifications::Event</tt>) to the sql method.
|
38
|
+
#
|
39
|
+
# Being an <tt>ActiveSupport::Notifications</tt> consumer,
|
40
|
+
# <tt>ActiveSupport::LogSubscriber</tt> exposes a simple interface to check if
|
41
|
+
# instrumented code raises an exception. It is common to log a different
|
42
|
+
# message in case of an error, and this can be achieved by extending
|
43
|
+
# the previous example:
|
44
|
+
#
|
45
|
+
# module ActiveRecord
|
46
|
+
# class LogSubscriber < ActiveSupport::LogSubscriber
|
47
|
+
# def sql(event)
|
48
|
+
# exception = event.payload[:exception]
|
49
|
+
#
|
50
|
+
# if exception
|
51
|
+
# exception_object = event.payload[:exception_object]
|
52
|
+
#
|
53
|
+
# error "[ERROR] #{event.payload[:name]}: #{exception.join(', ')} " \
|
54
|
+
# "(#{exception_object.backtrace.first})"
|
55
|
+
# else
|
56
|
+
# # standard logger code
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
# end
|
35
61
|
#
|
36
62
|
# 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.
|
63
|
+
# flushes all logs when the request finishes
|
64
|
+
# (via <tt>action_dispatch.callback</tt> notification) in a Rails environment.
|
39
65
|
class LogSubscriber < Subscriber
|
40
66
|
# Embed in a String to clear all previous ANSI sequences.
|
41
67
|
CLEAR = "\e[0m"
|
@@ -70,6 +96,11 @@ module ActiveSupport
|
|
70
96
|
def flush_all!
|
71
97
|
logger.flush if logger.respond_to?(:flush)
|
72
98
|
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def fetch_public_methods(subscriber, inherit_all)
|
102
|
+
subscriber.public_methods(inherit_all) - LogSubscriber.public_instance_methods(true)
|
103
|
+
end
|
73
104
|
end
|
74
105
|
|
75
106
|
def logger
|
@@ -89,7 +120,6 @@ module ActiveSupport
|
|
89
120
|
end
|
90
121
|
|
91
122
|
private
|
92
|
-
|
93
123
|
%w(info debug warn error fatal unknown).each do |level|
|
94
124
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
95
125
|
def #{level}(progname = nil, &block)
|