activesupport 6.0.6.1 → 6.1.7.3
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 +433 -464
- 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 +19 -2
- 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 +33 -35
- 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
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module ForkTracker # :nodoc:
|
5
|
+
module CoreExt
|
6
|
+
def fork(*)
|
7
|
+
if block_given?
|
8
|
+
super do
|
9
|
+
ForkTracker.check!
|
10
|
+
yield
|
11
|
+
end
|
12
|
+
else
|
13
|
+
unless pid = super
|
14
|
+
ForkTracker.check!
|
15
|
+
end
|
16
|
+
pid
|
17
|
+
end
|
18
|
+
end
|
19
|
+
ruby2_keywords(:fork) if respond_to?(:ruby2_keywords, true)
|
20
|
+
end
|
21
|
+
|
22
|
+
module CoreExtPrivate
|
23
|
+
include CoreExt
|
24
|
+
|
25
|
+
private
|
26
|
+
def fork(*)
|
27
|
+
super
|
28
|
+
end
|
29
|
+
ruby2_keywords(:fork) if respond_to?(:ruby2_keywords, true)
|
30
|
+
end
|
31
|
+
|
32
|
+
@pid = Process.pid
|
33
|
+
@callbacks = []
|
34
|
+
|
35
|
+
class << self
|
36
|
+
def check!
|
37
|
+
if @pid != Process.pid
|
38
|
+
@callbacks.each(&:call)
|
39
|
+
@pid = Process.pid
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def hook!
|
44
|
+
if Process.respond_to?(:fork)
|
45
|
+
::Object.prepend(CoreExtPrivate)
|
46
|
+
::Kernel.prepend(CoreExtPrivate)
|
47
|
+
::Kernel.singleton_class.prepend(CoreExt)
|
48
|
+
::Process.singleton_class.prepend(CoreExt)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def after_fork(&block)
|
53
|
+
@callbacks << block
|
54
|
+
block
|
55
|
+
end
|
56
|
+
|
57
|
+
def unregister(callback)
|
58
|
+
@callbacks.delete(callback)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
ActiveSupport::ForkTracker.hook!
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "active_support/core_ext/hash/keys"
|
4
4
|
require "active_support/core_ext/hash/reverse_merge"
|
5
5
|
require "active_support/core_ext/hash/except"
|
6
|
+
require "active_support/core_ext/hash/slice"
|
6
7
|
|
7
8
|
module ActiveSupport
|
8
9
|
# Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
|
@@ -69,7 +70,7 @@ module ActiveSupport
|
|
69
70
|
super()
|
70
71
|
update(constructor)
|
71
72
|
|
72
|
-
hash = constructor.to_hash
|
73
|
+
hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
|
73
74
|
self.default = hash.default if hash.default
|
74
75
|
self.default_proc = hash.default_proc if hash.default_proc
|
75
76
|
else
|
@@ -91,12 +92,12 @@ module ActiveSupport
|
|
91
92
|
#
|
92
93
|
# This value can be later fetched using either +:key+ or <tt>'key'</tt>.
|
93
94
|
def []=(key, value)
|
94
|
-
regular_writer(convert_key(key), convert_value(value,
|
95
|
+
regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
|
95
96
|
end
|
96
97
|
|
97
98
|
alias_method :store, :[]=
|
98
99
|
|
99
|
-
# Updates the receiver in-place, merging in the
|
100
|
+
# Updates the receiver in-place, merging in the hashes passed as arguments:
|
100
101
|
#
|
101
102
|
# hash_1 = ActiveSupport::HashWithIndifferentAccess.new
|
102
103
|
# hash_1[:key] = 'value'
|
@@ -106,11 +107,14 @@ module ActiveSupport
|
|
106
107
|
#
|
107
108
|
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
|
108
109
|
#
|
109
|
-
#
|
110
|
+
# hash = ActiveSupport::HashWithIndifferentAccess.new
|
111
|
+
# hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
|
112
|
+
#
|
113
|
+
# The arguments can be either an
|
110
114
|
# <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
|
111
115
|
# In either case the merge respects the semantics of indifferent access.
|
112
116
|
#
|
113
|
-
# If the argument is a regular hash with keys +:key+ and
|
117
|
+
# If the argument is a regular hash with keys +:key+ and <tt>"key"</tt> only one
|
114
118
|
# of the values end up in the receiver, but which one is unspecified.
|
115
119
|
#
|
116
120
|
# When given a block, the value for duplicated keys will be determined
|
@@ -121,18 +125,15 @@ module ActiveSupport
|
|
121
125
|
# hash_1[:key] = 10
|
122
126
|
# hash_2['key'] = 12
|
123
127
|
# hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
|
124
|
-
def update(
|
125
|
-
if
|
126
|
-
|
128
|
+
def update(*other_hashes, &block)
|
129
|
+
if other_hashes.size == 1
|
130
|
+
update_with_single_argument(other_hashes.first, block)
|
127
131
|
else
|
128
|
-
|
129
|
-
|
130
|
-
value = yield(convert_key(key), self[key], value)
|
131
|
-
end
|
132
|
-
regular_writer(convert_key(key), convert_value(value))
|
132
|
+
other_hashes.each do |other_hash|
|
133
|
+
update_with_single_argument(other_hash, block)
|
133
134
|
end
|
134
|
-
self
|
135
135
|
end
|
136
|
+
self
|
136
137
|
end
|
137
138
|
|
138
139
|
alias_method :merge!, :update
|
@@ -259,8 +260,8 @@ module ActiveSupport
|
|
259
260
|
# This method has the same semantics of +update+, except it does not
|
260
261
|
# modify the receiver but rather returns a new hash with indifferent
|
261
262
|
# access with the result of the merge.
|
262
|
-
def merge(
|
263
|
-
dup.update(
|
263
|
+
def merge(*hashes, &block)
|
264
|
+
dup.update(*hashes, &block)
|
264
265
|
end
|
265
266
|
|
266
267
|
# Like +merge+ but the other way around: Merges the receiver into the
|
@@ -293,6 +294,10 @@ module ActiveSupport
|
|
293
294
|
super(convert_key(key))
|
294
295
|
end
|
295
296
|
|
297
|
+
# Returns a hash with indifferent access that includes everything except given keys.
|
298
|
+
# hash = { a: "x", b: "y", c: 10 }.with_indifferent_access
|
299
|
+
# hash.except(:a, "b") # => {c: 10}.with_indifferent_access
|
300
|
+
# hash # => { a: "x", b: "y", c: 10 }.with_indifferent_access
|
296
301
|
def except(*keys)
|
297
302
|
slice(*self.keys - keys.map { |key| convert_key(key) })
|
298
303
|
end
|
@@ -357,40 +362,59 @@ module ActiveSupport
|
|
357
362
|
set_defaults(_new_hash)
|
358
363
|
|
359
364
|
each do |key, value|
|
360
|
-
_new_hash[key] = convert_value(value,
|
365
|
+
_new_hash[key] = convert_value(value, conversion: :to_hash)
|
361
366
|
end
|
362
367
|
_new_hash
|
363
368
|
end
|
364
369
|
|
365
370
|
private
|
366
|
-
|
367
|
-
key
|
371
|
+
if Symbol.method_defined?(:name)
|
372
|
+
def convert_key(key)
|
373
|
+
key.kind_of?(Symbol) ? key.name : key
|
374
|
+
end
|
375
|
+
else
|
376
|
+
def convert_key(key)
|
377
|
+
key.kind_of?(Symbol) ? key.to_s : key
|
378
|
+
end
|
368
379
|
end
|
369
380
|
|
370
|
-
def convert_value(value,
|
381
|
+
def convert_value(value, conversion: nil)
|
371
382
|
if value.is_a? Hash
|
372
|
-
if
|
383
|
+
if conversion == :to_hash
|
373
384
|
value.to_hash
|
374
385
|
else
|
375
386
|
value.nested_under_indifferent_access
|
376
387
|
end
|
377
388
|
elsif value.is_a?(Array)
|
378
|
-
if
|
389
|
+
if conversion != :assignment || value.frozen?
|
379
390
|
value = value.dup
|
380
391
|
end
|
381
|
-
value.map! { |e| convert_value(e,
|
392
|
+
value.map! { |e| convert_value(e, conversion: conversion) }
|
382
393
|
else
|
383
394
|
value
|
384
395
|
end
|
385
396
|
end
|
386
397
|
|
387
|
-
def set_defaults(target)
|
398
|
+
def set_defaults(target)
|
388
399
|
if default_proc
|
389
400
|
target.default_proc = default_proc.dup
|
390
401
|
else
|
391
402
|
target.default = default
|
392
403
|
end
|
393
404
|
end
|
405
|
+
|
406
|
+
def update_with_single_argument(other_hash, block)
|
407
|
+
if other_hash.is_a? HashWithIndifferentAccess
|
408
|
+
regular_update(other_hash, &block)
|
409
|
+
else
|
410
|
+
other_hash.to_hash.each_pair do |key, value|
|
411
|
+
if block && key?(key)
|
412
|
+
value = block.call(convert_key(key), self[key], value)
|
413
|
+
end
|
414
|
+
regular_writer(convert_key(key), convert_value(value))
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
394
418
|
end
|
395
419
|
end
|
396
420
|
|
@@ -12,9 +12,7 @@ module I18n
|
|
12
12
|
config.i18n.load_path = []
|
13
13
|
config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
|
14
14
|
|
15
|
-
|
16
|
-
config.eager_load_namespaces << I18n
|
17
|
-
end
|
15
|
+
config.eager_load_namespaces << I18n
|
18
16
|
|
19
17
|
# Set the i18n configuration after initialization since a lot of
|
20
18
|
# configuration is still usually done in application initializers.
|
@@ -50,8 +48,10 @@ module I18n
|
|
50
48
|
app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
|
51
49
|
when :load_path
|
52
50
|
I18n.load_path += value
|
51
|
+
when :raise_on_missing_translations
|
52
|
+
forward_raise_on_missing_translations_config(app)
|
53
53
|
else
|
54
|
-
I18n.
|
54
|
+
I18n.public_send("#{setting}=", value)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -64,8 +64,6 @@ module I18n
|
|
64
64
|
reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
|
65
65
|
I18n.load_path.keep_if { |p| File.exist?(p) }
|
66
66
|
I18n.load_path |= reloadable_paths.flat_map(&:existent)
|
67
|
-
|
68
|
-
I18n.reload!
|
69
67
|
end
|
70
68
|
|
71
69
|
app.reloaders << reloader
|
@@ -77,6 +75,16 @@ module I18n
|
|
77
75
|
@i18n_inited = true
|
78
76
|
end
|
79
77
|
|
78
|
+
def self.forward_raise_on_missing_translations_config(app)
|
79
|
+
ActiveSupport.on_load(:action_view) do
|
80
|
+
self.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
|
81
|
+
end
|
82
|
+
|
83
|
+
ActiveSupport.on_load(:action_controller) do
|
84
|
+
AbstractController::Translation.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
80
88
|
def self.include_fallbacks_module
|
81
89
|
I18n.backend.class.include(I18n::Backend::Fallbacks)
|
82
90
|
end
|
@@ -94,19 +102,6 @@ module I18n
|
|
94
102
|
[I18n.default_locale]
|
95
103
|
end
|
96
104
|
|
97
|
-
if args.empty? || args.first.is_a?(Hash)
|
98
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
99
|
-
Using I18n fallbacks with an empty `defaults` sets the defaults to
|
100
|
-
include the `default_locale`. This behavior will change in Rails 6.1.
|
101
|
-
If you desire the default locale to be included in the defaults, please
|
102
|
-
explicitly configure it with `config.i18n.fallbacks.defaults =
|
103
|
-
[I18n.default_locale]` or `config.i18n.fallbacks = [I18n.default_locale,
|
104
|
-
{...}]`. If you want to opt-in to the new behavior, use
|
105
|
-
`config.i18n.fallbacks.defaults = [nil, {...}]`.
|
106
|
-
MSG
|
107
|
-
args.unshift I18n.default_locale
|
108
|
-
end
|
109
|
-
|
110
105
|
I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
|
111
106
|
end
|
112
107
|
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "concurrent/map"
|
4
4
|
require "active_support/i18n"
|
5
|
-
require "active_support/deprecation"
|
6
5
|
|
7
6
|
module ActiveSupport
|
8
7
|
module Inflector
|
@@ -77,7 +76,7 @@ module ActiveSupport
|
|
77
76
|
# Private, for the test suite.
|
78
77
|
def initialize_dup(orig) # :nodoc:
|
79
78
|
%w(plurals singulars uncountables humans acronyms).each do |scope|
|
80
|
-
instance_variable_set("@#{scope}", orig.
|
79
|
+
instance_variable_set("@#{scope}", orig.public_send(scope).dup)
|
81
80
|
end
|
82
81
|
define_acronym_regex_patterns
|
83
82
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/inflections"
|
4
|
+
require "active_support/core_ext/object/blank"
|
4
5
|
|
5
6
|
module ActiveSupport
|
6
7
|
# The Inflector transforms words from singular to plural, class names to table
|
@@ -92,8 +93,7 @@ module ActiveSupport
|
|
92
93
|
return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
|
93
94
|
word = camel_cased_word.to_s.gsub("::", "/")
|
94
95
|
word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
|
95
|
-
word.gsub!(/([A-Z
|
96
|
-
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
96
|
+
word.gsub!(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }
|
97
97
|
word.tr!("-", "_")
|
98
98
|
word.downcase!
|
99
99
|
word
|
@@ -132,7 +132,7 @@ module ActiveSupport
|
|
132
132
|
|
133
133
|
result.sub!(/\A_+/, "")
|
134
134
|
unless keep_id_suffix
|
135
|
-
result.
|
135
|
+
result.delete_suffix!("_id")
|
136
136
|
end
|
137
137
|
result.tr!("_", " ")
|
138
138
|
|
@@ -172,7 +172,7 @@ module ActiveSupport
|
|
172
172
|
# titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
|
173
173
|
# titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
|
174
174
|
def titleize(word, keep_id_suffix: false)
|
175
|
-
humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`])[a-z]/) do |match|
|
175
|
+
humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`()])[a-z]/) do |match|
|
176
176
|
match.capitalize
|
177
177
|
end
|
178
178
|
end
|
@@ -269,32 +269,36 @@ module ActiveSupport
|
|
269
269
|
# NameError is raised when the name is not in CamelCase or the constant is
|
270
270
|
# unknown.
|
271
271
|
def constantize(camel_cased_word)
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
if
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
const
|
272
|
+
if camel_cased_word.blank? || !camel_cased_word.include?("::")
|
273
|
+
Object.const_get(camel_cased_word)
|
274
|
+
else
|
275
|
+
names = camel_cased_word.split("::")
|
276
|
+
|
277
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
278
|
+
Object.const_get(camel_cased_word) if names.empty?
|
279
|
+
|
280
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
281
|
+
names.shift if names.size > 1 && names.first.empty?
|
282
|
+
|
283
|
+
names.inject(Object) do |constant, name|
|
284
|
+
if constant == Object
|
285
|
+
constant.const_get(name)
|
286
|
+
else
|
287
|
+
candidate = constant.const_get(name)
|
288
|
+
next candidate if constant.const_defined?(name, false)
|
289
|
+
next candidate unless Object.const_defined?(name)
|
290
|
+
|
291
|
+
# Go down the ancestors to check if it is owned directly. The check
|
292
|
+
# stops when we reach Object or the end of ancestors tree.
|
293
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
294
|
+
break const if ancestor == Object
|
295
|
+
break ancestor if ancestor.const_defined?(name, false)
|
296
|
+
const
|
297
|
+
end
|
298
|
+
|
299
|
+
# owner is in Object, so raise
|
300
|
+
constant.const_get(name, false)
|
294
301
|
end
|
295
|
-
|
296
|
-
# owner is in Object, so raise
|
297
|
-
constant.const_get(name, false)
|
298
302
|
end
|
299
303
|
end
|
300
304
|
end
|
@@ -326,10 +330,9 @@ module ActiveSupport
|
|
326
330
|
rescue NameError => e
|
327
331
|
raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
|
328
332
|
e.name.to_s == camel_cased_word.to_s)
|
329
|
-
rescue ArgumentError => e
|
330
|
-
raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message)
|
331
333
|
rescue LoadError => e
|
332
|
-
|
334
|
+
message = e.respond_to?(:original_message) ? e.original_message : e.message
|
335
|
+
raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(message)
|
333
336
|
end
|
334
337
|
|
335
338
|
# Returns the suffix that should be added to a number to denote the position
|
@@ -371,7 +374,7 @@ module ActiveSupport
|
|
371
374
|
|
372
375
|
last = parts.pop
|
373
376
|
|
374
|
-
parts.reverse
|
377
|
+
parts.reverse!.inject(last) do |acc, part|
|
375
378
|
part.empty? ? acc : "#{part}(::#{acc})?"
|
376
379
|
end
|
377
380
|
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
|
#
|
@@ -62,9 +64,7 @@ module ActiveSupport
|
|
62
64
|
def transliterate(string, replacement = "?", locale: nil)
|
63
65
|
string = string.dup if string.frozen?
|
64
66
|
raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
|
65
|
-
|
66
|
-
allowed_encodings = [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030]
|
67
|
-
raise ArgumentError, "Can not transliterate strings with #{string.encoding} encoding" unless allowed_encodings.include?(string.encoding)
|
67
|
+
raise ArgumentError, "Cannot transliterate strings with #{string.encoding} encoding" unless ALLOWED_ENCODINGS_FOR_TRANSLITERATE.include?(string.encoding)
|
68
68
|
|
69
69
|
input_encoding = string.encoding
|
70
70
|
|
@@ -117,7 +117,7 @@ module ActiveSupport
|
|
117
117
|
# If the optional parameter +locale+ is specified,
|
118
118
|
# the word will be parameterized as a word of that language.
|
119
119
|
# By default, this parameter is set to <tt>nil</tt> and it will use
|
120
|
-
# the configured <tt>I18n.locale
|
120
|
+
# the configured <tt>I18n.locale</tt>.
|
121
121
|
def parameterize(string, separator: "-", preserve_case: false, locale: nil)
|
122
122
|
# Replace accented chars with their ASCII equivalents.
|
123
123
|
parameterized_string = transliterate(string, locale: locale)
|
@@ -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.
|
@@ -63,8 +63,8 @@ module ActiveSupport
|
|
63
63
|
when Array
|
64
64
|
data.map! { |d| convert_dates_from(d) }
|
65
65
|
when Hash
|
66
|
-
data.
|
67
|
-
|
66
|
+
data.transform_values! do |value|
|
67
|
+
convert_dates_from(value)
|
68
68
|
end
|
69
69
|
else
|
70
70
|
data
|
@@ -93,7 +93,11 @@ module ActiveSupport
|
|
93
93
|
when Numeric, NilClass, TrueClass, FalseClass
|
94
94
|
value.as_json
|
95
95
|
when Hash
|
96
|
-
|
96
|
+
result = {}
|
97
|
+
value.each do |k, v|
|
98
|
+
result[jsonify(k)] = jsonify(v)
|
99
|
+
end
|
100
|
+
result
|
97
101
|
when Array
|
98
102
|
value.map { |v| jsonify(v) }
|
99
103
|
else
|
@@ -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()
|
@@ -29,6 +29,9 @@ module ActiveSupport
|
|
29
29
|
# subscriber, the line above should be called after your
|
30
30
|
# <tt>ActiveRecord::LogSubscriber</tt> definition.
|
31
31
|
#
|
32
|
+
# A logger also needs to be set with <tt>ActiveRecord::LogSubscriber.logger=</tt>.
|
33
|
+
# This is assigned automatically in a Rails environment.
|
34
|
+
#
|
32
35
|
# After configured, whenever a <tt>"sql.active_record"</tt> notification is published,
|
33
36
|
# it will properly dispatch the event
|
34
37
|
# (<tt>ActiveSupport::Notifications::Event</tt>) to the sql method.
|
@@ -93,6 +96,11 @@ module ActiveSupport
|
|
93
96
|
def flush_all!
|
94
97
|
logger.flush if logger.respond_to?(:flush)
|
95
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
|
96
104
|
end
|
97
105
|
|
98
106
|
def logger
|
@@ -14,7 +14,7 @@ module ActiveSupport
|
|
14
14
|
# ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT)
|
15
15
|
# # => true
|
16
16
|
def self.logger_outputs_to?(logger, *sources)
|
17
|
-
logdev = logger.instance_variable_get(
|
17
|
+
logdev = logger.instance_variable_get(:@logdev)
|
18
18
|
logger_source = logdev.dev if logdev.respond_to?(:dev)
|
19
19
|
sources.any? { |source| source == logger_source }
|
20
20
|
end
|
@@ -4,19 +4,6 @@ require "active_support/concern"
|
|
4
4
|
require "active_support/core_ext/module/attribute_accessors"
|
5
5
|
require "active_support/logger_thread_safe_level"
|
6
6
|
|
7
|
-
module LoggerSilence
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
included do
|
11
|
-
ActiveSupport::Deprecation.warn(
|
12
|
-
"Including LoggerSilence is deprecated and will be removed in Rails 6.1. " \
|
13
|
-
"Please use `ActiveSupport::LoggerSilence` instead"
|
14
|
-
)
|
15
|
-
|
16
|
-
include ActiveSupport::LoggerSilence
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
7
|
module ActiveSupport
|
21
8
|
module LoggerSilence
|
22
9
|
extend ActiveSupport::Concern
|
@@ -27,19 +14,8 @@ module ActiveSupport
|
|
27
14
|
end
|
28
15
|
|
29
16
|
# Silences the logger for the duration of the block.
|
30
|
-
def silence(
|
31
|
-
|
32
|
-
begin
|
33
|
-
old_local_level = local_level
|
34
|
-
self.local_level = temporary_level
|
35
|
-
|
36
|
-
yield self
|
37
|
-
ensure
|
38
|
-
self.local_level = old_local_level
|
39
|
-
end
|
40
|
-
else
|
41
|
-
yield self
|
42
|
-
end
|
17
|
+
def silence(severity = Logger::ERROR)
|
18
|
+
silencer ? log_at(severity) { yield self } : yield(self)
|
43
19
|
end
|
44
20
|
end
|
45
21
|
end
|