activesupport 5.2.8.1 → 6.1.6.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 +426 -424
- 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/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/digest/uuid.rb +1 -0
- 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 -13
- 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 +53 -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 +120 -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/digest.rb +2 -0
- 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 +82 -33
- 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 +3 -3
- 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 +2 -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 +34 -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 +54 -27
- 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
@@ -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!
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require "active_support/core_ext/hash/keys"
|
4
4
|
require "active_support/core_ext/hash/reverse_merge"
|
5
|
+
require "active_support/core_ext/hash/except"
|
6
|
+
require "active_support/core_ext/hash/slice"
|
5
7
|
|
6
8
|
module ActiveSupport
|
7
9
|
# Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
|
@@ -68,7 +70,7 @@ module ActiveSupport
|
|
68
70
|
super()
|
69
71
|
update(constructor)
|
70
72
|
|
71
|
-
hash = constructor.to_hash
|
73
|
+
hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
|
72
74
|
self.default = hash.default if hash.default
|
73
75
|
self.default_proc = hash.default_proc if hash.default_proc
|
74
76
|
else
|
@@ -90,12 +92,12 @@ module ActiveSupport
|
|
90
92
|
#
|
91
93
|
# This value can be later fetched using either +:key+ or <tt>'key'</tt>.
|
92
94
|
def []=(key, value)
|
93
|
-
regular_writer(convert_key(key), convert_value(value,
|
95
|
+
regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
|
94
96
|
end
|
95
97
|
|
96
98
|
alias_method :store, :[]=
|
97
99
|
|
98
|
-
# Updates the receiver in-place, merging in the
|
100
|
+
# Updates the receiver in-place, merging in the hashes passed as arguments:
|
99
101
|
#
|
100
102
|
# hash_1 = ActiveSupport::HashWithIndifferentAccess.new
|
101
103
|
# hash_1[:key] = 'value'
|
@@ -105,11 +107,14 @@ module ActiveSupport
|
|
105
107
|
#
|
106
108
|
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
|
107
109
|
#
|
108
|
-
#
|
110
|
+
# hash = ActiveSupport::HashWithIndifferentAccess.new
|
111
|
+
# hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
|
112
|
+
#
|
113
|
+
# The arguments can be either an
|
109
114
|
# <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
|
110
115
|
# In either case the merge respects the semantics of indifferent access.
|
111
116
|
#
|
112
|
-
# 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
|
113
118
|
# of the values end up in the receiver, but which one is unspecified.
|
114
119
|
#
|
115
120
|
# When given a block, the value for duplicated keys will be determined
|
@@ -120,18 +125,15 @@ module ActiveSupport
|
|
120
125
|
# hash_1[:key] = 10
|
121
126
|
# hash_2['key'] = 12
|
122
127
|
# hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
|
123
|
-
def update(
|
124
|
-
if
|
125
|
-
|
128
|
+
def update(*other_hashes, &block)
|
129
|
+
if other_hashes.size == 1
|
130
|
+
update_with_single_argument(other_hashes.first, block)
|
126
131
|
else
|
127
|
-
|
128
|
-
|
129
|
-
value = yield(convert_key(key), self[key], value)
|
130
|
-
end
|
131
|
-
regular_writer(convert_key(key), convert_value(value))
|
132
|
+
other_hashes.each do |other_hash|
|
133
|
+
update_with_single_argument(other_hash, block)
|
132
134
|
end
|
133
|
-
self
|
134
135
|
end
|
136
|
+
self
|
135
137
|
end
|
136
138
|
|
137
139
|
alias_method :merge!, :update
|
@@ -190,20 +192,18 @@ module ActiveSupport
|
|
190
192
|
super(convert_key(key), *extras)
|
191
193
|
end
|
192
194
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
super(*args)
|
206
|
-
end
|
195
|
+
# Same as <tt>Hash#dig</tt> where the key passed as argument can be
|
196
|
+
# either a string or a symbol:
|
197
|
+
#
|
198
|
+
# counters = ActiveSupport::HashWithIndifferentAccess.new
|
199
|
+
# counters[:foo] = { bar: 1 }
|
200
|
+
#
|
201
|
+
# counters.dig('foo', 'bar') # => 1
|
202
|
+
# counters.dig(:foo, :bar) # => 1
|
203
|
+
# counters.dig(:zoo) # => nil
|
204
|
+
def dig(*args)
|
205
|
+
args[0] = convert_key(args[0]) if args.size > 0
|
206
|
+
super(*args)
|
207
207
|
end
|
208
208
|
|
209
209
|
# Same as <tt>Hash#default</tt> where the key passed as argument can be
|
@@ -226,8 +226,8 @@ module ActiveSupport
|
|
226
226
|
# hash[:a] = 'x'
|
227
227
|
# hash[:b] = 'y'
|
228
228
|
# hash.values_at('a', 'b') # => ["x", "y"]
|
229
|
-
def values_at(*
|
230
|
-
|
229
|
+
def values_at(*keys)
|
230
|
+
super(*keys.map { |key| convert_key(key) })
|
231
231
|
end
|
232
232
|
|
233
233
|
# Returns an array of the values at the specified indices, but also
|
@@ -240,8 +240,8 @@ module ActiveSupport
|
|
240
240
|
# hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
|
241
241
|
# hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
|
242
242
|
def fetch_values(*indices, &block)
|
243
|
-
indices.
|
244
|
-
end
|
243
|
+
super(*indices.map { |key| convert_key(key) }, &block)
|
244
|
+
end
|
245
245
|
|
246
246
|
# Returns a shallow copy of the hash.
|
247
247
|
#
|
@@ -260,8 +260,8 @@ module ActiveSupport
|
|
260
260
|
# This method has the same semantics of +update+, except it does not
|
261
261
|
# modify the receiver but rather returns a new hash with indifferent
|
262
262
|
# access with the result of the merge.
|
263
|
-
def merge(
|
264
|
-
dup.update(
|
263
|
+
def merge(*hashes, &block)
|
264
|
+
dup.update(*hashes, &block)
|
265
265
|
end
|
266
266
|
|
267
267
|
# Like +merge+ but the other way around: Merges the receiver into the
|
@@ -294,6 +294,15 @@ module ActiveSupport
|
|
294
294
|
super(convert_key(key))
|
295
295
|
end
|
296
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
|
301
|
+
def except(*keys)
|
302
|
+
slice(*self.keys - keys.map { |key| convert_key(key) })
|
303
|
+
end
|
304
|
+
alias_method :without, :except
|
305
|
+
|
297
306
|
def stringify_keys!; self end
|
298
307
|
def deep_stringify_keys!; self end
|
299
308
|
def stringify_keys; dup end
|
@@ -353,40 +362,59 @@ module ActiveSupport
|
|
353
362
|
set_defaults(_new_hash)
|
354
363
|
|
355
364
|
each do |key, value|
|
356
|
-
_new_hash[key] = convert_value(value,
|
365
|
+
_new_hash[key] = convert_value(value, conversion: :to_hash)
|
357
366
|
end
|
358
367
|
_new_hash
|
359
368
|
end
|
360
369
|
|
361
370
|
private
|
362
|
-
|
363
|
-
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
|
364
379
|
end
|
365
380
|
|
366
|
-
def convert_value(value,
|
381
|
+
def convert_value(value, conversion: nil)
|
367
382
|
if value.is_a? Hash
|
368
|
-
if
|
383
|
+
if conversion == :to_hash
|
369
384
|
value.to_hash
|
370
385
|
else
|
371
386
|
value.nested_under_indifferent_access
|
372
387
|
end
|
373
388
|
elsif value.is_a?(Array)
|
374
|
-
if
|
389
|
+
if conversion != :assignment || value.frozen?
|
375
390
|
value = value.dup
|
376
391
|
end
|
377
|
-
value.map! { |e| convert_value(e,
|
392
|
+
value.map! { |e| convert_value(e, conversion: conversion) }
|
378
393
|
else
|
379
394
|
value
|
380
395
|
end
|
381
396
|
end
|
382
397
|
|
383
|
-
def set_defaults(target)
|
398
|
+
def set_defaults(target)
|
384
399
|
if default_proc
|
385
400
|
target.default_proc = default_proc.dup
|
386
401
|
else
|
387
402
|
target.default = default
|
388
403
|
end
|
389
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
|
390
418
|
end
|
391
419
|
end
|
392
420
|
|
data/lib/active_support/i18n.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support"
|
4
|
-
require "active_support/file_update_checker"
|
5
4
|
require "active_support/core_ext/array/wrap"
|
6
5
|
|
7
6
|
# :enddoc:
|
@@ -13,6 +12,8 @@ module I18n
|
|
13
12
|
config.i18n.load_path = []
|
14
13
|
config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
|
15
14
|
|
15
|
+
config.eager_load_namespaces << I18n
|
16
|
+
|
16
17
|
# Set the i18n configuration after initialization since a lot of
|
17
18
|
# configuration is still usually done in application initializers.
|
18
19
|
config.after_initialize do |app|
|
@@ -47,8 +48,10 @@ module I18n
|
|
47
48
|
app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
|
48
49
|
when :load_path
|
49
50
|
I18n.load_path += value
|
51
|
+
when :raise_on_missing_translations
|
52
|
+
forward_raise_on_missing_translations_config(app)
|
50
53
|
else
|
51
|
-
I18n.
|
54
|
+
I18n.public_send("#{setting}=", value)
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
@@ -61,8 +64,6 @@ module I18n
|
|
61
64
|
reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
|
62
65
|
I18n.load_path.keep_if { |p| File.exist?(p) }
|
63
66
|
I18n.load_path |= reloadable_paths.flat_map(&:existent)
|
64
|
-
|
65
|
-
I18n.reload!
|
66
67
|
end
|
67
68
|
|
68
69
|
app.reloaders << reloader
|
@@ -74,6 +75,16 @@ module I18n
|
|
74
75
|
@i18n_inited = true
|
75
76
|
end
|
76
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
|
+
|
77
88
|
def self.include_fallbacks_module
|
78
89
|
I18n.backend.class.include(I18n::Backend::Fallbacks)
|
79
90
|
end
|
@@ -91,10 +102,6 @@ module I18n
|
|
91
102
|
[I18n.default_locale]
|
92
103
|
end
|
93
104
|
|
94
|
-
if args.empty? || args.first.is_a?(Hash)
|
95
|
-
args.unshift I18n.default_locale
|
96
|
-
end
|
97
|
-
|
98
105
|
I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
|
99
106
|
end
|
100
107
|
|
@@ -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
|