activesupport 5.2.0 → 6.1.0
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 +362 -333
- 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 +33 -33
- data/lib/active_support/cache/mem_cache_store.rb +31 -29
- 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 +84 -45
- data/lib/active_support/cache/strategy/local_cache.rb +41 -26
- data/lib/active_support/cache.rb +174 -113
- data/lib/active_support/callbacks.rb +81 -64
- data/lib/active_support/concern.rb +76 -5
- 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 +46 -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.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +171 -70
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- 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 +7 -2
- data/lib/active_support/core_ext/object/to_query.rb +5 -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 +82 -0
- 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/range.rb +1 -1
- 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 +69 -12
- 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 +50 -3
- data/lib/active_support/core_ext/time/conversions.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +7 -5
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +15 -2
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +118 -35
- data/lib/active_support/deprecation/behaviors.rb +20 -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 +21 -13
- data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
- data/lib/active_support/deprecation/reporting.rb +51 -8
- 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 +90 -38
- data/lib/active_support/encrypted_configuration.rb +1 -5
- data/lib/active_support/encrypted_file.rb +23 -5
- 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 +1 -0
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +2 -2
- data/lib/active_support/hash_with_indifferent_access.rb +78 -41
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +16 -5
- data/lib/active_support/inflector/inflections.rb +2 -7
- data/lib/active_support/inflector/methods.rb +50 -57
- 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 +52 -7
- 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 +8 -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/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 -24
- data/lib/active_support/tagged_logging.rb +42 -8
- data/lib/active_support/test_case.rb +92 -1
- 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/setup_and_teardown.rb +5 -9
- 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 -18
- 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 +57 -30
- 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 -25
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -0,0 +1,62 @@
|
|
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
|
+
end
|
20
|
+
|
21
|
+
module CoreExtPrivate
|
22
|
+
include CoreExt
|
23
|
+
|
24
|
+
private
|
25
|
+
def fork(*)
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@pid = Process.pid
|
31
|
+
@callbacks = []
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def check!
|
35
|
+
if @pid != Process.pid
|
36
|
+
@callbacks.each(&:call)
|
37
|
+
@pid = Process.pid
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def hook!
|
42
|
+
if Process.respond_to?(:fork)
|
43
|
+
::Object.prepend(CoreExtPrivate)
|
44
|
+
::Kernel.prepend(CoreExtPrivate)
|
45
|
+
::Kernel.singleton_class.prepend(CoreExt)
|
46
|
+
::Process.singleton_class.prepend(CoreExt)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def after_fork(&block)
|
51
|
+
@callbacks << block
|
52
|
+
block
|
53
|
+
end
|
54
|
+
|
55
|
+
def unregister(callback)
|
56
|
+
@callbacks.delete(callback)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
ActiveSupport::ForkTracker.hook!
|
@@ -2,6 +2,7 @@
|
|
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"
|
5
6
|
|
6
7
|
module ActiveSupport
|
7
8
|
# Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
|
@@ -68,7 +69,7 @@ module ActiveSupport
|
|
68
69
|
super()
|
69
70
|
update(constructor)
|
70
71
|
|
71
|
-
hash = constructor.to_hash
|
72
|
+
hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
|
72
73
|
self.default = hash.default if hash.default
|
73
74
|
self.default_proc = hash.default_proc if hash.default_proc
|
74
75
|
else
|
@@ -90,12 +91,12 @@ module ActiveSupport
|
|
90
91
|
#
|
91
92
|
# This value can be later fetched using either +:key+ or <tt>'key'</tt>.
|
92
93
|
def []=(key, value)
|
93
|
-
regular_writer(convert_key(key), convert_value(value,
|
94
|
+
regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
|
94
95
|
end
|
95
96
|
|
96
97
|
alias_method :store, :[]=
|
97
98
|
|
98
|
-
# Updates the receiver in-place, merging in the
|
99
|
+
# Updates the receiver in-place, merging in the hashes passed as arguments:
|
99
100
|
#
|
100
101
|
# hash_1 = ActiveSupport::HashWithIndifferentAccess.new
|
101
102
|
# hash_1[:key] = 'value'
|
@@ -105,7 +106,10 @@ module ActiveSupport
|
|
105
106
|
#
|
106
107
|
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
|
107
108
|
#
|
108
|
-
#
|
109
|
+
# hash = ActiveSupport::HashWithIndifferentAccess.new
|
110
|
+
# hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
|
111
|
+
#
|
112
|
+
# The arguments can be either an
|
109
113
|
# <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
|
110
114
|
# In either case the merge respects the semantics of indifferent access.
|
111
115
|
#
|
@@ -120,18 +124,15 @@ module ActiveSupport
|
|
120
124
|
# hash_1[:key] = 10
|
121
125
|
# hash_2['key'] = 12
|
122
126
|
# hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
|
123
|
-
def update(
|
124
|
-
if
|
125
|
-
|
127
|
+
def update(*other_hashes, &block)
|
128
|
+
if other_hashes.size == 1
|
129
|
+
update_with_single_argument(other_hashes.first, block)
|
126
130
|
else
|
127
|
-
|
128
|
-
|
129
|
-
value = yield(convert_key(key), self[key], value)
|
130
|
-
end
|
131
|
-
regular_writer(convert_key(key), convert_value(value))
|
131
|
+
other_hashes.each do |other_hash|
|
132
|
+
update_with_single_argument(other_hash, block)
|
132
133
|
end
|
133
|
-
self
|
134
134
|
end
|
135
|
+
self
|
135
136
|
end
|
136
137
|
|
137
138
|
alias_method :merge!, :update
|
@@ -163,6 +164,19 @@ module ActiveSupport
|
|
163
164
|
super(convert_key(key))
|
164
165
|
end
|
165
166
|
|
167
|
+
# Same as <tt>Hash#assoc</tt> where the key passed as argument can be
|
168
|
+
# either a string or a symbol:
|
169
|
+
#
|
170
|
+
# counters = ActiveSupport::HashWithIndifferentAccess.new
|
171
|
+
# counters[:foo] = 1
|
172
|
+
#
|
173
|
+
# counters.assoc('foo') # => ["foo", 1]
|
174
|
+
# counters.assoc(:foo) # => ["foo", 1]
|
175
|
+
# counters.assoc(:zoo) # => nil
|
176
|
+
def assoc(key)
|
177
|
+
super(convert_key(key))
|
178
|
+
end
|
179
|
+
|
166
180
|
# Same as <tt>Hash#fetch</tt> where the key passed as argument can be
|
167
181
|
# either a string or a symbol:
|
168
182
|
#
|
@@ -177,20 +191,18 @@ module ActiveSupport
|
|
177
191
|
super(convert_key(key), *extras)
|
178
192
|
end
|
179
193
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
super(*args)
|
193
|
-
end
|
194
|
+
# Same as <tt>Hash#dig</tt> where the key passed as argument can be
|
195
|
+
# either a string or a symbol:
|
196
|
+
#
|
197
|
+
# counters = ActiveSupport::HashWithIndifferentAccess.new
|
198
|
+
# counters[:foo] = { bar: 1 }
|
199
|
+
#
|
200
|
+
# counters.dig('foo', 'bar') # => 1
|
201
|
+
# counters.dig(:foo, :bar) # => 1
|
202
|
+
# counters.dig(:zoo) # => nil
|
203
|
+
def dig(*args)
|
204
|
+
args[0] = convert_key(args[0]) if args.size > 0
|
205
|
+
super(*args)
|
194
206
|
end
|
195
207
|
|
196
208
|
# Same as <tt>Hash#default</tt> where the key passed as argument can be
|
@@ -213,8 +225,8 @@ module ActiveSupport
|
|
213
225
|
# hash[:a] = 'x'
|
214
226
|
# hash[:b] = 'y'
|
215
227
|
# hash.values_at('a', 'b') # => ["x", "y"]
|
216
|
-
def values_at(*
|
217
|
-
|
228
|
+
def values_at(*keys)
|
229
|
+
super(*keys.map { |key| convert_key(key) })
|
218
230
|
end
|
219
231
|
|
220
232
|
# Returns an array of the values at the specified indices, but also
|
@@ -227,8 +239,8 @@ module ActiveSupport
|
|
227
239
|
# hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
|
228
240
|
# hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
|
229
241
|
def fetch_values(*indices, &block)
|
230
|
-
indices.
|
231
|
-
end
|
242
|
+
super(*indices.map { |key| convert_key(key) }, &block)
|
243
|
+
end
|
232
244
|
|
233
245
|
# Returns a shallow copy of the hash.
|
234
246
|
#
|
@@ -247,8 +259,8 @@ module ActiveSupport
|
|
247
259
|
# This method has the same semantics of +update+, except it does not
|
248
260
|
# modify the receiver but rather returns a new hash with indifferent
|
249
261
|
# access with the result of the merge.
|
250
|
-
def merge(
|
251
|
-
dup.update(
|
262
|
+
def merge(*hashes, &block)
|
263
|
+
dup.update(*hashes, &block)
|
252
264
|
end
|
253
265
|
|
254
266
|
# Like +merge+ but the other way around: Merges the receiver into the
|
@@ -281,6 +293,11 @@ module ActiveSupport
|
|
281
293
|
super(convert_key(key))
|
282
294
|
end
|
283
295
|
|
296
|
+
def except(*keys)
|
297
|
+
slice(*self.keys - keys.map { |key| convert_key(key) })
|
298
|
+
end
|
299
|
+
alias_method :without, :except
|
300
|
+
|
284
301
|
def stringify_keys!; self end
|
285
302
|
def deep_stringify_keys!; self end
|
286
303
|
def stringify_keys; dup end
|
@@ -288,6 +305,7 @@ module ActiveSupport
|
|
288
305
|
undef :symbolize_keys!
|
289
306
|
undef :deep_symbolize_keys!
|
290
307
|
def symbolize_keys; to_hash.symbolize_keys! end
|
308
|
+
alias_method :to_options, :symbolize_keys
|
291
309
|
def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
|
292
310
|
def to_options!; self end
|
293
311
|
|
@@ -339,40 +357,59 @@ module ActiveSupport
|
|
339
357
|
set_defaults(_new_hash)
|
340
358
|
|
341
359
|
each do |key, value|
|
342
|
-
_new_hash[key] = convert_value(value,
|
360
|
+
_new_hash[key] = convert_value(value, conversion: :to_hash)
|
343
361
|
end
|
344
362
|
_new_hash
|
345
363
|
end
|
346
364
|
|
347
365
|
private
|
348
|
-
|
349
|
-
key
|
366
|
+
if Symbol.method_defined?(:name)
|
367
|
+
def convert_key(key)
|
368
|
+
key.kind_of?(Symbol) ? key.name : key
|
369
|
+
end
|
370
|
+
else
|
371
|
+
def convert_key(key)
|
372
|
+
key.kind_of?(Symbol) ? key.to_s : key
|
373
|
+
end
|
350
374
|
end
|
351
375
|
|
352
|
-
def convert_value(value,
|
376
|
+
def convert_value(value, conversion: nil)
|
353
377
|
if value.is_a? Hash
|
354
|
-
if
|
378
|
+
if conversion == :to_hash
|
355
379
|
value.to_hash
|
356
380
|
else
|
357
381
|
value.nested_under_indifferent_access
|
358
382
|
end
|
359
383
|
elsif value.is_a?(Array)
|
360
|
-
if
|
384
|
+
if conversion != :assignment || value.frozen?
|
361
385
|
value = value.dup
|
362
386
|
end
|
363
|
-
value.map! { |e| convert_value(e,
|
387
|
+
value.map! { |e| convert_value(e, conversion: conversion) }
|
364
388
|
else
|
365
389
|
value
|
366
390
|
end
|
367
391
|
end
|
368
392
|
|
369
|
-
def set_defaults(target)
|
393
|
+
def set_defaults(target)
|
370
394
|
if default_proc
|
371
395
|
target.default_proc = default_proc.dup
|
372
396
|
else
|
373
397
|
target.default = default
|
374
398
|
end
|
375
399
|
end
|
400
|
+
|
401
|
+
def update_with_single_argument(other_hash, block)
|
402
|
+
if other_hash.is_a? HashWithIndifferentAccess
|
403
|
+
regular_update(other_hash, &block)
|
404
|
+
else
|
405
|
+
other_hash.to_hash.each_pair do |key, value|
|
406
|
+
if block && key?(key)
|
407
|
+
value = block.call(convert_key(key), self[key], value)
|
408
|
+
end
|
409
|
+
regular_writer(convert_key(key), convert_value(value))
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
376
413
|
end
|
377
414
|
end
|
378
415
|
|
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
|
@@ -88,7 +99,7 @@ module I18n
|
|
88
99
|
when Hash, Array
|
89
100
|
Array.wrap(fallbacks)
|
90
101
|
else # TrueClass
|
91
|
-
[]
|
102
|
+
[I18n.default_locale]
|
92
103
|
end
|
93
104
|
|
94
105
|
I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
|
@@ -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,8 +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
|
331
|
-
|
334
|
+
rescue LoadError => e
|
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)
|
332
337
|
end
|
333
338
|
|
334
339
|
# Returns the suffix that should be added to a number to denote the position
|
@@ -341,18 +346,7 @@ module ActiveSupport
|
|
341
346
|
# ordinal(-11) # => "th"
|
342
347
|
# ordinal(-1021) # => "st"
|
343
348
|
def ordinal(number)
|
344
|
-
|
345
|
-
|
346
|
-
if (11..13).include?(abs_number % 100)
|
347
|
-
"th"
|
348
|
-
else
|
349
|
-
case abs_number % 10
|
350
|
-
when 1; "st"
|
351
|
-
when 2; "nd"
|
352
|
-
when 3; "rd"
|
353
|
-
else "th"
|
354
|
-
end
|
355
|
-
end
|
349
|
+
I18n.translate("number.nth.ordinals", number: number)
|
356
350
|
end
|
357
351
|
|
358
352
|
# Turns a number into an ordinal string used to denote the position in an
|
@@ -365,24 +359,23 @@ module ActiveSupport
|
|
365
359
|
# ordinalize(-11) # => "-11th"
|
366
360
|
# ordinalize(-1021) # => "-1021st"
|
367
361
|
def ordinalize(number)
|
368
|
-
"
|
362
|
+
I18n.translate("number.nth.ordinalized", number: number)
|
369
363
|
end
|
370
364
|
|
371
365
|
private
|
372
|
-
|
373
366
|
# Mounts a regular expression, returned as a string to ease interpolation,
|
374
367
|
# that will match part by part the given constant.
|
375
368
|
#
|
376
369
|
# const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
|
377
370
|
# const_regexp("::") # => "::"
|
378
371
|
def const_regexp(camel_cased_word)
|
379
|
-
parts = camel_cased_word.split("::"
|
372
|
+
parts = camel_cased_word.split("::")
|
380
373
|
|
381
374
|
return Regexp.escape(camel_cased_word) if parts.blank?
|
382
375
|
|
383
376
|
last = parts.pop
|
384
377
|
|
385
|
-
parts.reverse
|
378
|
+
parts.reverse!.inject(last) do |acc, part|
|
386
379
|
part.empty? ? acc : "#{part}(::#{acc})?"
|
387
380
|
end
|
388
381
|
end
|