activesupport 6.0.0 → 6.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +381 -349
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/active_support.rb +13 -1
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +3 -4
  8. data/lib/active_support/benchmarkable.rb +1 -1
  9. data/lib/active_support/cache.rb +101 -59
  10. data/lib/active_support/cache/file_store.rb +11 -11
  11. data/lib/active_support/cache/mem_cache_store.rb +34 -33
  12. data/lib/active_support/cache/memory_store.rb +52 -31
  13. data/lib/active_support/cache/null_store.rb +3 -3
  14. data/lib/active_support/cache/redis_cache_store.rb +38 -33
  15. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  16. data/lib/active_support/callbacks.rb +65 -59
  17. data/lib/active_support/concern.rb +46 -2
  18. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  19. data/lib/active_support/concurrency/share_lock.rb +0 -1
  20. data/lib/active_support/configurable.rb +3 -3
  21. data/lib/active_support/configuration_file.rb +46 -0
  22. data/lib/active_support/core_ext.rb +1 -1
  23. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  24. data/lib/active_support/core_ext/benchmark.rb +2 -2
  25. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  26. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  27. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  28. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  29. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  30. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  31. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  32. data/lib/active_support/core_ext/enumerable.rb +76 -4
  33. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  34. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  35. data/lib/active_support/core_ext/hash/except.rb +1 -1
  36. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  37. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  38. data/lib/active_support/core_ext/load_error.rb +1 -1
  39. data/lib/active_support/core_ext/marshal.rb +2 -0
  40. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  41. data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
  42. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
  43. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  44. data/lib/active_support/core_ext/module/delegation.rb +46 -29
  45. data/lib/active_support/core_ext/module/introspection.rb +2 -25
  46. data/lib/active_support/core_ext/name_error.rb +29 -2
  47. data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
  48. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  49. data/lib/active_support/core_ext/object/json.rb +13 -2
  50. data/lib/active_support/core_ext/object/try.rb +4 -2
  51. data/lib/active_support/core_ext/range/compare_range.rb +15 -3
  52. data/lib/active_support/core_ext/range/each.rb +0 -1
  53. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  54. data/lib/active_support/core_ext/regexp.rb +8 -1
  55. data/lib/active_support/core_ext/string/access.rb +5 -24
  56. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  57. data/lib/active_support/core_ext/string/inflections.rb +38 -4
  58. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  59. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  60. data/lib/active_support/core_ext/string/output_safety.rb +12 -11
  61. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  62. data/lib/active_support/core_ext/symbol.rb +3 -0
  63. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  64. data/lib/active_support/core_ext/time/calculations.rb +27 -3
  65. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  66. data/lib/active_support/core_ext/uri.rb +5 -1
  67. data/lib/active_support/current_attributes.rb +7 -2
  68. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  69. data/lib/active_support/dependencies.rb +42 -20
  70. data/lib/active_support/dependencies/zeitwerk_integration.rb +9 -2
  71. data/lib/active_support/deprecation.rb +6 -1
  72. data/lib/active_support/deprecation/behaviors.rb +15 -2
  73. data/lib/active_support/deprecation/disallowed.rb +56 -0
  74. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  75. data/lib/active_support/deprecation/method_wrappers.rb +13 -6
  76. data/lib/active_support/deprecation/proxy_wrappers.rb +6 -2
  77. data/lib/active_support/deprecation/reporting.rb +50 -7
  78. data/lib/active_support/descendants_tracker.rb +6 -3
  79. data/lib/active_support/duration.rb +86 -35
  80. data/lib/active_support/duration/iso8601_parser.rb +0 -1
  81. data/lib/active_support/duration/iso8601_serializer.rb +15 -10
  82. data/lib/active_support/encrypted_file.rb +20 -3
  83. data/lib/active_support/environment_inquirer.rb +20 -0
  84. data/lib/active_support/evented_file_update_checker.rb +69 -134
  85. data/lib/active_support/file_update_checker.rb +0 -1
  86. data/lib/active_support/fork_tracker.rb +62 -0
  87. data/lib/active_support/gem_version.rb +2 -2
  88. data/lib/active_support/hash_with_indifferent_access.rb +43 -24
  89. data/lib/active_support/i18n_railtie.rb +15 -16
  90. data/lib/active_support/inflector/inflections.rb +1 -3
  91. data/lib/active_support/inflector/methods.rb +36 -33
  92. data/lib/active_support/inflector/transliterate.rb +4 -4
  93. data/lib/active_support/json/decoding.rb +4 -5
  94. data/lib/active_support/json/encoding.rb +5 -1
  95. data/lib/active_support/key_generator.rb +1 -1
  96. data/lib/active_support/lazy_load_hooks.rb +0 -1
  97. data/lib/active_support/locale/en.rb +4 -2
  98. data/lib/active_support/locale/en.yml +7 -3
  99. data/lib/active_support/log_subscriber.rb +8 -1
  100. data/lib/active_support/logger.rb +2 -2
  101. data/lib/active_support/logger_silence.rb +2 -26
  102. data/lib/active_support/logger_thread_safe_level.rb +34 -12
  103. data/lib/active_support/message_encryptor.rb +5 -8
  104. data/lib/active_support/message_verifier.rb +7 -7
  105. data/lib/active_support/messages/metadata.rb +11 -2
  106. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  107. data/lib/active_support/messages/rotator.rb +10 -9
  108. data/lib/active_support/multibyte/chars.rb +5 -44
  109. data/lib/active_support/multibyte/unicode.rb +9 -84
  110. data/lib/active_support/notifications.rb +32 -5
  111. data/lib/active_support/notifications/fanout.rb +23 -8
  112. data/lib/active_support/notifications/instrumenter.rb +7 -16
  113. data/lib/active_support/number_helper.rb +33 -14
  114. data/lib/active_support/number_helper/number_converter.rb +5 -6
  115. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -7
  116. data/lib/active_support/number_helper/number_to_delimited_converter.rb +0 -1
  117. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -2
  118. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -2
  119. data/lib/active_support/number_helper/number_to_phone_converter.rb +0 -1
  120. data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -4
  121. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  122. data/lib/active_support/option_merger.rb +22 -3
  123. data/lib/active_support/ordered_hash.rb +1 -1
  124. data/lib/active_support/ordered_options.rb +13 -3
  125. data/lib/active_support/parameter_filter.rb +17 -13
  126. data/lib/active_support/per_thread_registry.rb +1 -1
  127. data/lib/active_support/rails.rb +1 -4
  128. data/lib/active_support/railtie.rb +23 -1
  129. data/lib/active_support/rescuable.rb +4 -4
  130. data/lib/active_support/secure_compare_rotator.rb +51 -0
  131. data/lib/active_support/security_utils.rb +19 -12
  132. data/lib/active_support/string_inquirer.rb +4 -3
  133. data/lib/active_support/subscriber.rb +12 -7
  134. data/lib/active_support/tagged_logging.rb +29 -4
  135. data/lib/active_support/testing/assertions.rb +18 -11
  136. data/lib/active_support/testing/parallelization.rb +12 -89
  137. data/lib/active_support/testing/parallelization/server.rb +78 -0
  138. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  139. data/lib/active_support/testing/stream.rb +0 -1
  140. data/lib/active_support/testing/time_helpers.rb +40 -5
  141. data/lib/active_support/time_with_zone.rb +67 -43
  142. data/lib/active_support/values/time_zone.rb +20 -10
  143. data/lib/active_support/xml_mini.rb +0 -1
  144. data/lib/active_support/xml_mini/jdom.rb +0 -1
  145. data/lib/active_support/xml_mini/rexml.rb +8 -1
  146. metadata +39 -38
  147. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  148. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  149. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  150. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  151. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  152. data/lib/active_support/core_ext/range/include_range.rb +0 -9
@@ -8,8 +8,8 @@ module ActiveSupport
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 6
11
- MINOR = 0
12
- TINY = 0
11
+ MINOR = 1
12
+ TINY = 3
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -69,7 +69,7 @@ module ActiveSupport
69
69
  super()
70
70
  update(constructor)
71
71
 
72
- hash = constructor.to_hash
72
+ hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
73
73
  self.default = hash.default if hash.default
74
74
  self.default_proc = hash.default_proc if hash.default_proc
75
75
  else
@@ -91,12 +91,12 @@ module ActiveSupport
91
91
  #
92
92
  # This value can be later fetched using either +:key+ or <tt>'key'</tt>.
93
93
  def []=(key, value)
94
- regular_writer(convert_key(key), convert_value(value, for: :assignment))
94
+ regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
95
95
  end
96
96
 
97
97
  alias_method :store, :[]=
98
98
 
99
- # 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:
100
100
  #
101
101
  # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
102
102
  # hash_1[:key] = 'value'
@@ -106,11 +106,14 @@ module ActiveSupport
106
106
  #
107
107
  # hash_1.update(hash_2) # => {"key"=>"New Value!"}
108
108
  #
109
- # 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
110
113
  # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
111
114
  # In either case the merge respects the semantics of indifferent access.
112
115
  #
113
- # If the argument is a regular hash with keys +:key+ and +"key"+ only one
116
+ # If the argument is a regular hash with keys +:key+ and <tt>"key"</tt> only one
114
117
  # of the values end up in the receiver, but which one is unspecified.
115
118
  #
116
119
  # When given a block, the value for duplicated keys will be determined
@@ -121,18 +124,15 @@ module ActiveSupport
121
124
  # hash_1[:key] = 10
122
125
  # hash_2['key'] = 12
123
126
  # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
124
- def update(other_hash)
125
- if other_hash.is_a? HashWithIndifferentAccess
126
- super(other_hash)
127
+ def update(*other_hashes, &block)
128
+ if other_hashes.size == 1
129
+ update_with_single_argument(other_hashes.first, block)
127
130
  else
128
- other_hash.to_hash.each_pair do |key, value|
129
- if block_given? && key?(key)
130
- value = yield(convert_key(key), self[key], value)
131
- end
132
- regular_writer(convert_key(key), convert_value(value))
131
+ other_hashes.each do |other_hash|
132
+ update_with_single_argument(other_hash, block)
133
133
  end
134
- self
135
134
  end
135
+ self
136
136
  end
137
137
 
138
138
  alias_method :merge!, :update
@@ -259,8 +259,8 @@ module ActiveSupport
259
259
  # This method has the same semantics of +update+, except it does not
260
260
  # modify the receiver but rather returns a new hash with indifferent
261
261
  # access with the result of the merge.
262
- def merge(hash, &block)
263
- dup.update(hash, &block)
262
+ def merge(*hashes, &block)
263
+ dup.update(*hashes, &block)
264
264
  end
265
265
 
266
266
  # Like +merge+ but the other way around: Merges the receiver into the
@@ -357,40 +357,59 @@ module ActiveSupport
357
357
  set_defaults(_new_hash)
358
358
 
359
359
  each do |key, value|
360
- _new_hash[key] = convert_value(value, for: :to_hash)
360
+ _new_hash[key] = convert_value(value, conversion: :to_hash)
361
361
  end
362
362
  _new_hash
363
363
  end
364
364
 
365
365
  private
366
- def convert_key(key) # :doc:
367
- 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
368
374
  end
369
375
 
370
- def convert_value(value, options = {}) # :doc:
376
+ def convert_value(value, conversion: nil)
371
377
  if value.is_a? Hash
372
- if options[:for] == :to_hash
378
+ if conversion == :to_hash
373
379
  value.to_hash
374
380
  else
375
381
  value.nested_under_indifferent_access
376
382
  end
377
383
  elsif value.is_a?(Array)
378
- if options[:for] != :assignment || value.frozen?
384
+ if conversion != :assignment || value.frozen?
379
385
  value = value.dup
380
386
  end
381
- value.map! { |e| convert_value(e, options) }
387
+ value.map! { |e| convert_value(e, conversion: conversion) }
382
388
  else
383
389
  value
384
390
  end
385
391
  end
386
392
 
387
- def set_defaults(target) # :doc:
393
+ def set_defaults(target)
388
394
  if default_proc
389
395
  target.default_proc = default_proc.dup
390
396
  else
391
397
  target.default = default
392
398
  end
393
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
394
413
  end
395
414
  end
396
415
 
@@ -12,6 +12,8 @@ module I18n
12
12
  config.i18n.load_path = []
13
13
  config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
14
14
 
15
+ config.eager_load_namespaces << I18n
16
+
15
17
  # Set the i18n configuration after initialization since a lot of
16
18
  # configuration is still usually done in application initializers.
17
19
  config.after_initialize do |app|
@@ -46,8 +48,10 @@ module I18n
46
48
  app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
47
49
  when :load_path
48
50
  I18n.load_path += value
51
+ when :raise_on_missing_translations
52
+ forward_raise_on_missing_translations_config(app)
49
53
  else
50
- I18n.send("#{setting}=", value)
54
+ I18n.public_send("#{setting}=", value)
51
55
  end
52
56
  end
53
57
 
@@ -60,8 +64,6 @@ module I18n
60
64
  reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
61
65
  I18n.load_path.keep_if { |p| File.exist?(p) }
62
66
  I18n.load_path |= reloadable_paths.flat_map(&:existent)
63
-
64
- I18n.reload!
65
67
  end
66
68
 
67
69
  app.reloaders << reloader
@@ -73,6 +75,16 @@ module I18n
73
75
  @i18n_inited = true
74
76
  end
75
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
+
76
88
  def self.include_fallbacks_module
77
89
  I18n.backend.class.include(I18n::Backend::Fallbacks)
78
90
  end
@@ -90,19 +102,6 @@ module I18n
90
102
  [I18n.default_locale]
91
103
  end
92
104
 
93
- if args.empty? || args.first.is_a?(Hash)
94
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
95
- Using I18n fallbacks with an empty `defaults` sets the defaults to
96
- include the `default_locale`. This behavior will change in Rails 6.1.
97
- If you desire the default locale to be included in the defaults, please
98
- explicitly configure it with `config.i18n.fallbacks.defaults =
99
- [I18n.default_locale]` or `config.i18n.fallbacks = [I18n.default_locale,
100
- {...}]`. If you want to opt-in to the new behavior, use
101
- `config.i18n.fallbacks.defaults = [nil, {...}]`.
102
- MSG
103
- args.unshift I18n.default_locale
104
- end
105
-
106
105
  I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
107
106
  end
108
107
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "concurrent/map"
4
4
  require "active_support/i18n"
5
- require "active_support/deprecation"
6
5
 
7
6
  module ActiveSupport
8
7
  module Inflector
@@ -77,7 +76,7 @@ module ActiveSupport
77
76
  # Private, for the test suite.
78
77
  def initialize_dup(orig) # :nodoc:
79
78
  %w(plurals singulars uncountables humans acronyms).each do |scope|
80
- instance_variable_set("@#{scope}", orig.send(scope).dup)
79
+ instance_variable_set("@#{scope}", orig.public_send(scope).dup)
81
80
  end
82
81
  define_acronym_regex_patterns
83
82
  end
@@ -230,7 +229,6 @@ module ActiveSupport
230
229
  end
231
230
 
232
231
  private
233
-
234
232
  def define_acronym_regex_patterns
235
233
  @acronym_regex = @acronyms.empty? ? /(?=a)b/ : /#{@acronyms.values.join("|")}/
236
234
  @acronyms_camelize_regex = /^(?:#{@acronym_regex}(?=\b|[A-Z_])|\w)/
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/inflections"
4
+ require "active_support/core_ext/object/blank"
4
5
 
5
6
  module ActiveSupport
6
7
  # The Inflector transforms words from singular to plural, class names to table
@@ -132,7 +133,7 @@ module ActiveSupport
132
133
 
133
134
  result.sub!(/\A_+/, "")
134
135
  unless keep_id_suffix
135
- result.sub!(/_id\z/, "")
136
+ result.delete_suffix!("_id")
136
137
  end
137
138
  result.tr!("_", " ")
138
139
 
@@ -172,7 +173,7 @@ module ActiveSupport
172
173
  # titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
173
174
  # titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
174
175
  def titleize(word, keep_id_suffix: false)
175
- 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|
176
177
  match.capitalize
177
178
  end
178
179
  end
@@ -196,7 +197,7 @@ module ActiveSupport
196
197
  #
197
198
  # Singular names are not handled correctly:
198
199
  #
199
- # classify('calculus') # => "Calculus"
200
+ # classify('calculus') # => "Calculu"
200
201
  def classify(table_name)
201
202
  # strip out any leading schema name
202
203
  camelize(singularize(table_name.to_s.sub(/.*\./, "")))
@@ -269,32 +270,36 @@ module ActiveSupport
269
270
  # NameError is raised when the name is not in CamelCase or the constant is
270
271
  # unknown.
271
272
  def constantize(camel_cased_word)
272
- names = camel_cased_word.split("::")
273
-
274
- # Trigger a built-in NameError exception including the ill-formed constant in the message.
275
- Object.const_get(camel_cased_word) if names.empty?
276
-
277
- # Remove the first blank element in case of '::ClassName' notation.
278
- names.shift if names.size > 1 && names.first.empty?
279
-
280
- names.inject(Object) do |constant, name|
281
- if constant == Object
282
- constant.const_get(name)
283
- else
284
- candidate = constant.const_get(name)
285
- next candidate if constant.const_defined?(name, false)
286
- next candidate unless Object.const_defined?(name)
287
-
288
- # Go down the ancestors to check if it is owned directly. The check
289
- # stops when we reach Object or the end of ancestors tree.
290
- constant = constant.ancestors.inject(constant) do |const, ancestor|
291
- break const if ancestor == Object
292
- break ancestor if ancestor.const_defined?(name, false)
293
- 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)
294
302
  end
295
-
296
- # owner is in Object, so raise
297
- constant.const_get(name, false)
298
303
  end
299
304
  end
300
305
  end
@@ -326,10 +331,9 @@ module ActiveSupport
326
331
  rescue NameError => e
327
332
  raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
328
333
  e.name.to_s == camel_cased_word.to_s)
329
- rescue ArgumentError => e
330
- raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message)
331
334
  rescue LoadError => e
332
- 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)
333
337
  end
334
338
 
335
339
  # Returns the suffix that should be added to a number to denote the position
@@ -359,7 +363,6 @@ module ActiveSupport
359
363
  end
360
364
 
361
365
  private
362
-
363
366
  # Mounts a regular expression, returned as a string to ease interpolation,
364
367
  # that will match part by part the given constant.
365
368
  #
@@ -372,7 +375,7 @@ module ActiveSupport
372
375
 
373
376
  last = parts.pop
374
377
 
375
- parts.reverse.inject(last) do |acc, part|
378
+ parts.reverse!.inject(last) do |acc, part|
376
379
  part.empty? ? acc : "#{part}(::#{acc})?"
377
380
  end
378
381
  end
@@ -5,6 +5,8 @@ require "active_support/i18n"
5
5
 
6
6
  module ActiveSupport
7
7
  module Inflector
8
+ ALLOWED_ENCODINGS_FOR_TRANSLITERATE = [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030].freeze
9
+
8
10
  # Replaces non-ASCII characters with an ASCII approximation, or if none
9
11
  # exists, a replacement character which defaults to "?".
10
12
  #
@@ -62,9 +64,7 @@ module ActiveSupport
62
64
  def transliterate(string, replacement = "?", locale: nil)
63
65
  string = string.dup if string.frozen?
64
66
  raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
65
-
66
- allowed_encodings = [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030]
67
- raise ArgumentError, "Can not transliterate strings with #{string.encoding} encoding" unless allowed_encodings.include?(string.encoding)
67
+ raise ArgumentError, "Cannot transliterate strings with #{string.encoding} encoding" unless ALLOWED_ENCODINGS_FOR_TRANSLITERATE.include?(string.encoding)
68
68
 
69
69
  input_encoding = string.encoding
70
70
 
@@ -117,7 +117,7 @@ module ActiveSupport
117
117
  # If the optional parameter +locale+ is specified,
118
118
  # the word will be parameterized as a word of that language.
119
119
  # By default, this parameter is set to <tt>nil</tt> and it will use
120
- # the configured <tt>I18n.locale<tt>.
120
+ # the configured <tt>I18n.locale</tt>.
121
121
  def parameterize(string, separator: "-", preserve_case: false, locale: nil)
122
122
  # Replace accented chars with their ASCII equivalents.
123
123
  parameterized_string = transliterate(string, locale: locale)
@@ -10,8 +10,8 @@ module ActiveSupport
10
10
 
11
11
  module JSON
12
12
  # matches YAML-formatted dates
13
- DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/
14
- DATETIME_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)$/
13
+ DATE_REGEX = /\A\d{4}-\d{2}-\d{2}\z/
14
+ DATETIME_REGEX = /\A(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)\z/
15
15
 
16
16
  class << self
17
17
  # Parses a JSON string (JavaScript Object Notation) into a hash.
@@ -44,7 +44,6 @@ module ActiveSupport
44
44
  end
45
45
 
46
46
  private
47
-
48
47
  def convert_dates_from(data)
49
48
  case data
50
49
  when nil
@@ -64,8 +63,8 @@ module ActiveSupport
64
63
  when Array
65
64
  data.map! { |d| convert_dates_from(d) }
66
65
  when Hash
67
- data.each do |key, value|
68
- data[key] = convert_dates_from(value)
66
+ data.transform_values! do |value|
67
+ convert_dates_from(value)
69
68
  end
70
69
  else
71
70
  data
@@ -93,7 +93,11 @@ module ActiveSupport
93
93
  when Numeric, NilClass, TrueClass, FalseClass
94
94
  value.as_json
95
95
  when Hash
96
- Hash[value.map { |k, v| [jsonify(k), jsonify(v)] }]
96
+ result = {}
97
+ value.each do |k, v|
98
+ result[jsonify(k)] = jsonify(v)
99
+ end
100
+ result
97
101
  when Array
98
102
  value.map { |v| jsonify(v) }
99
103
  else
@@ -35,7 +35,7 @@ module ActiveSupport
35
35
 
36
36
  # Returns a derived key suitable for use.
37
37
  def generate_key(*args)
38
- @cache_keys[args.join] ||= @key_generator.generate_key(*args)
38
+ @cache_keys[args.join("|")] ||= @key_generator.generate_key(*args)
39
39
  end
40
40
  end
41
41
  end