activesupport 5.2.4.4 → 6.1.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.

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +353 -435
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support.rb +14 -1
  6. data/lib/active_support/actionable_error.rb +48 -0
  7. data/lib/active_support/array_inquirer.rb +4 -2
  8. data/lib/active_support/backtrace_cleaner.rb +29 -3
  9. data/lib/active_support/benchmarkable.rb +1 -1
  10. data/lib/active_support/cache.rb +142 -78
  11. data/lib/active_support/cache/file_store.rb +33 -33
  12. data/lib/active_support/cache/mem_cache_store.rb +32 -20
  13. data/lib/active_support/cache/memory_store.rb +59 -33
  14. data/lib/active_support/cache/null_store.rb +8 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +70 -43
  16. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  17. data/lib/active_support/callbacks.rb +81 -64
  18. data/lib/active_support/concern.rb +70 -3
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  20. data/lib/active_support/concurrency/share_lock.rb +0 -1
  21. data/lib/active_support/configurable.rb +10 -14
  22. data/lib/active_support/configuration_file.rb +46 -0
  23. data/lib/active_support/core_ext.rb +1 -1
  24. data/lib/active_support/core_ext/array.rb +1 -1
  25. data/lib/active_support/core_ext/array/access.rb +18 -6
  26. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/benchmark.rb +2 -2
  29. data/lib/active_support/core_ext/class/attribute.rb +32 -47
  30. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  31. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  32. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
  34. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  35. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  36. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  37. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  38. data/lib/active_support/core_ext/enumerable.rb +171 -75
  39. data/lib/active_support/core_ext/hash.rb +1 -2
  40. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  41. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  42. data/lib/active_support/core_ext/hash/except.rb +2 -2
  43. data/lib/active_support/core_ext/hash/keys.rb +1 -30
  44. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  45. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  46. data/lib/active_support/core_ext/kernel.rb +0 -1
  47. data/lib/active_support/core_ext/load_error.rb +1 -1
  48. data/lib/active_support/core_ext/marshal.rb +2 -0
  49. data/lib/active_support/core_ext/module.rb +0 -1
  50. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  51. data/lib/active_support/core_ext/module/attribute_accessors.rb +30 -39
  52. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
  53. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  54. data/lib/active_support/core_ext/module/delegation.rb +76 -33
  55. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  56. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  57. data/lib/active_support/core_ext/name_error.rb +29 -2
  58. data/lib/active_support/core_ext/numeric.rb +0 -1
  59. data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
  60. data/lib/active_support/core_ext/object/blank.rb +1 -2
  61. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  62. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  63. data/lib/active_support/core_ext/object/json.rb +14 -2
  64. data/lib/active_support/core_ext/object/try.rb +17 -7
  65. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  66. data/lib/active_support/core_ext/range/compare_range.rb +34 -13
  67. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  68. data/lib/active_support/core_ext/range/each.rb +0 -1
  69. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  70. data/lib/active_support/core_ext/regexp.rb +8 -5
  71. data/lib/active_support/core_ext/securerandom.rb +23 -3
  72. data/lib/active_support/core_ext/string/access.rb +5 -16
  73. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  74. data/lib/active_support/core_ext/string/filters.rb +42 -1
  75. data/lib/active_support/core_ext/string/inflections.rb +45 -6
  76. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  77. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  78. data/lib/active_support/core_ext/string/output_safety.rb +70 -13
  79. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  80. data/lib/active_support/core_ext/string/strip.rb +3 -1
  81. data/lib/active_support/core_ext/symbol.rb +3 -0
  82. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  83. data/lib/active_support/core_ext/time/calculations.rb +50 -3
  84. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  85. data/lib/active_support/core_ext/uri.rb +6 -1
  86. data/lib/active_support/current_attributes.rb +15 -2
  87. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  88. data/lib/active_support/dependencies.rb +109 -34
  89. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  90. data/lib/active_support/deprecation.rb +6 -1
  91. data/lib/active_support/deprecation/behaviors.rb +16 -3
  92. data/lib/active_support/deprecation/disallowed.rb +56 -0
  93. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  94. data/lib/active_support/deprecation/method_wrappers.rb +18 -23
  95. data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
  96. data/lib/active_support/deprecation/reporting.rb +50 -7
  97. data/lib/active_support/descendants_tracker.rb +59 -9
  98. data/lib/active_support/duration.rb +90 -38
  99. data/lib/active_support/duration/iso8601_parser.rb +2 -4
  100. data/lib/active_support/duration/iso8601_serializer.rb +18 -14
  101. data/lib/active_support/encrypted_configuration.rb +0 -4
  102. data/lib/active_support/encrypted_file.rb +22 -4
  103. data/lib/active_support/environment_inquirer.rb +20 -0
  104. data/lib/active_support/evented_file_update_checker.rb +82 -117
  105. data/lib/active_support/execution_wrapper.rb +1 -0
  106. data/lib/active_support/file_update_checker.rb +0 -1
  107. data/lib/active_support/fork_tracker.rb +62 -0
  108. data/lib/active_support/gem_version.rb +4 -4
  109. data/lib/active_support/hash_with_indifferent_access.rb +64 -41
  110. data/lib/active_support/i18n.rb +1 -0
  111. data/lib/active_support/i18n_railtie.rb +15 -8
  112. data/lib/active_support/inflector/inflections.rb +2 -7
  113. data/lib/active_support/inflector/methods.rb +49 -58
  114. data/lib/active_support/inflector/transliterate.rb +47 -18
  115. data/lib/active_support/json/decoding.rb +25 -26
  116. data/lib/active_support/json/encoding.rb +11 -3
  117. data/lib/active_support/key_generator.rb +1 -33
  118. data/lib/active_support/lazy_load_hooks.rb +5 -2
  119. data/lib/active_support/locale/en.rb +33 -0
  120. data/lib/active_support/locale/en.yml +7 -3
  121. data/lib/active_support/log_subscriber.rb +39 -9
  122. data/lib/active_support/logger.rb +2 -17
  123. data/lib/active_support/logger_silence.rb +11 -19
  124. data/lib/active_support/logger_thread_safe_level.rb +50 -6
  125. data/lib/active_support/message_encryptor.rb +8 -13
  126. data/lib/active_support/message_verifier.rb +10 -10
  127. data/lib/active_support/messages/metadata.rb +11 -2
  128. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  129. data/lib/active_support/messages/rotator.rb +10 -9
  130. data/lib/active_support/multibyte/chars.rb +10 -68
  131. data/lib/active_support/multibyte/unicode.rb +15 -327
  132. data/lib/active_support/notifications.rb +72 -8
  133. data/lib/active_support/notifications/fanout.rb +116 -16
  134. data/lib/active_support/notifications/instrumenter.rb +71 -9
  135. data/lib/active_support/number_helper.rb +38 -12
  136. data/lib/active_support/number_helper/number_converter.rb +5 -6
  137. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
  138. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
  139. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  140. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
  141. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  142. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  143. data/lib/active_support/number_helper/number_to_rounded_converter.rb +8 -7
  144. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  145. data/lib/active_support/option_merger.rb +22 -3
  146. data/lib/active_support/ordered_hash.rb +1 -1
  147. data/lib/active_support/ordered_options.rb +13 -3
  148. data/lib/active_support/parameter_filter.rb +133 -0
  149. data/lib/active_support/per_thread_registry.rb +1 -1
  150. data/lib/active_support/rails.rb +1 -10
  151. data/lib/active_support/railtie.rb +23 -1
  152. data/lib/active_support/reloader.rb +4 -5
  153. data/lib/active_support/rescuable.rb +4 -4
  154. data/lib/active_support/secure_compare_rotator.rb +51 -0
  155. data/lib/active_support/security_utils.rb +19 -12
  156. data/lib/active_support/string_inquirer.rb +4 -3
  157. data/lib/active_support/subscriber.rb +72 -28
  158. data/lib/active_support/tagged_logging.rb +42 -8
  159. data/lib/active_support/test_case.rb +91 -0
  160. data/lib/active_support/testing/assertions.rb +30 -9
  161. data/lib/active_support/testing/deprecation.rb +0 -1
  162. data/lib/active_support/testing/file_fixtures.rb +2 -0
  163. data/lib/active_support/testing/isolation.rb +2 -2
  164. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  165. data/lib/active_support/testing/parallelization.rb +51 -0
  166. data/lib/active_support/testing/parallelization/server.rb +78 -0
  167. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  168. data/lib/active_support/testing/stream.rb +1 -2
  169. data/lib/active_support/testing/time_helpers.rb +47 -12
  170. data/lib/active_support/time_with_zone.rb +81 -47
  171. data/lib/active_support/values/time_zone.rb +32 -17
  172. data/lib/active_support/xml_mini.rb +2 -10
  173. data/lib/active_support/xml_mini/jdom.rb +2 -3
  174. data/lib/active_support/xml_mini/libxml.rb +2 -2
  175. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  176. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  177. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  178. data/lib/active_support/xml_mini/rexml.rb +10 -3
  179. metadata +58 -32
  180. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  181. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  182. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  183. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  184. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  185. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  186. data/lib/active_support/core_ext/range/include_range.rb +0 -3
  187. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -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, for: :assignment))
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 hash passed as argument:
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
- # The argument can be either an
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(other_hash)
124
- if other_hash.is_a? HashWithIndifferentAccess
125
- super(other_hash)
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
- other_hash.to_hash.each_pair do |key, value|
128
- if block_given? && key?(key)
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
@@ -190,20 +191,18 @@ module ActiveSupport
190
191
  super(convert_key(key), *extras)
191
192
  end
192
193
 
193
- if Hash.new.respond_to?(:dig)
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)
206
- 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)
207
206
  end
208
207
 
209
208
  # Same as <tt>Hash#default</tt> where the key passed as argument can be
@@ -226,8 +225,8 @@ module ActiveSupport
226
225
  # hash[:a] = 'x'
227
226
  # hash[:b] = 'y'
228
227
  # hash.values_at('a', 'b') # => ["x", "y"]
229
- def values_at(*indices)
230
- indices.collect { |key| self[convert_key(key)] }
228
+ def values_at(*keys)
229
+ super(*keys.map { |key| convert_key(key) })
231
230
  end
232
231
 
233
232
  # Returns an array of the values at the specified indices, but also
@@ -240,8 +239,8 @@ module ActiveSupport
240
239
  # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
241
240
  # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
242
241
  def fetch_values(*indices, &block)
243
- indices.collect { |key| fetch(key, &block) }
244
- end if Hash.method_defined?(:fetch_values)
242
+ super(*indices.map { |key| convert_key(key) }, &block)
243
+ end
245
244
 
246
245
  # Returns a shallow copy of the hash.
247
246
  #
@@ -260,8 +259,8 @@ module ActiveSupport
260
259
  # This method has the same semantics of +update+, except it does not
261
260
  # modify the receiver but rather returns a new hash with indifferent
262
261
  # access with the result of the merge.
263
- def merge(hash, &block)
264
- dup.update(hash, &block)
262
+ def merge(*hashes, &block)
263
+ dup.update(*hashes, &block)
265
264
  end
266
265
 
267
266
  # Like +merge+ but the other way around: Merges the receiver into the
@@ -294,6 +293,11 @@ module ActiveSupport
294
293
  super(convert_key(key))
295
294
  end
296
295
 
296
+ def except(*keys)
297
+ slice(*self.keys - keys.map { |key| convert_key(key) })
298
+ end
299
+ alias_method :without, :except
300
+
297
301
  def stringify_keys!; self end
298
302
  def deep_stringify_keys!; self end
299
303
  def stringify_keys; dup end
@@ -353,40 +357,59 @@ module ActiveSupport
353
357
  set_defaults(_new_hash)
354
358
 
355
359
  each do |key, value|
356
- _new_hash[key] = convert_value(value, for: :to_hash)
360
+ _new_hash[key] = convert_value(value, conversion: :to_hash)
357
361
  end
358
362
  _new_hash
359
363
  end
360
364
 
361
365
  private
362
- def convert_key(key) # :doc:
363
- key.kind_of?(Symbol) ? key.to_s : 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
364
374
  end
365
375
 
366
- def convert_value(value, options = {}) # :doc:
376
+ def convert_value(value, conversion: nil)
367
377
  if value.is_a? Hash
368
- if options[:for] == :to_hash
378
+ if conversion == :to_hash
369
379
  value.to_hash
370
380
  else
371
381
  value.nested_under_indifferent_access
372
382
  end
373
383
  elsif value.is_a?(Array)
374
- if options[:for] != :assignment || value.frozen?
384
+ if conversion != :assignment || value.frozen?
375
385
  value = value.dup
376
386
  end
377
- value.map! { |e| convert_value(e, options) }
387
+ value.map! { |e| convert_value(e, conversion: conversion) }
378
388
  else
379
389
  value
380
390
  end
381
391
  end
382
392
 
383
- def set_defaults(target) # :doc:
393
+ def set_defaults(target)
384
394
  if default_proc
385
395
  target.default_proc = default_proc.dup
386
396
  else
387
397
  target.default = default
388
398
  end
389
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
390
413
  end
391
414
  end
392
415
 
@@ -13,3 +13,4 @@ require "active_support/lazy_load_hooks"
13
13
 
14
14
  ActiveSupport.run_load_hooks(:i18n)
15
15
  I18n.load_path << File.expand_path("locale/en.yml", __dir__)
16
+ I18n.load_path << File.expand_path("locale/en.rb", __dir__)
@@ -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.send("#{setting}=", value)
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, :acronym_regex
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.send(scope).dup)
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/regexp"
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!("/".freeze, "::".freeze)
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("::".freeze, "/".freeze)
95
- word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_'.freeze }#{$2.downcase}" }
96
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze)
97
- word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze)
98
- word.tr!("-".freeze, "_".freeze)
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_+/, "".freeze)
134
+ result.sub!(/\A_+/, "")
135
135
  unless keep_id_suffix
136
- result.sub!(/_id\z/, "".freeze)
136
+ result.delete_suffix!("_id")
137
137
  end
138
- result.tr!("_".freeze, " ".freeze)
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') # => "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(/.*\./, "".freeze)))
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("_".freeze, "-".freeze)
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
- names = camel_cased_word.split("::".freeze)
274
-
275
- # Trigger a built-in NameError exception including the ill-formed constant in the message.
276
- Object.const_get(camel_cased_word) if names.empty?
277
-
278
- # Remove the first blank element in case of '::ClassName' notation.
279
- names.shift if names.size > 1 && names.first.empty?
280
-
281
- names.inject(Object) do |constant, name|
282
- if constant == Object
283
- constant.const_get(name)
284
- else
285
- candidate = constant.const_get(name)
286
- next candidate if constant.const_defined?(name, false)
287
- next candidate unless Object.const_defined?(name)
288
-
289
- # Go down the ancestors to check if it is owned directly. The check
290
- # stops when we reach Object or the end of ancestors tree.
291
- constant = constant.ancestors.inject(constant) do |const, ancestor|
292
- break const if ancestor == Object
293
- break ancestor if ancestor.const_defined?(name, false)
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
- raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(e.message)
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
- abs_number = number.to_i.abs
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
- "#{number}#{ordinal(number)}"
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("::".freeze)
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.inject(last) do |acc, part|
378
+ parts.reverse!.inject(last) do |acc, part|
388
379
  part.empty? ? acc : "#{part}(::#{acc})?"
389
380
  end
390
381
  end