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

Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +327 -408
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -2
  5. data/lib/active_support.rb +2 -1
  6. data/lib/active_support/actionable_error.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +28 -1
  8. data/lib/active_support/cache.rb +45 -23
  9. data/lib/active_support/cache/file_store.rb +22 -22
  10. data/lib/active_support/cache/mem_cache_store.rb +17 -2
  11. data/lib/active_support/cache/memory_store.rb +7 -2
  12. data/lib/active_support/cache/null_store.rb +5 -0
  13. data/lib/active_support/cache/redis_cache_store.rb +47 -25
  14. data/lib/active_support/callbacks.rb +16 -5
  15. data/lib/active_support/concern.rb +24 -1
  16. data/lib/active_support/configurable.rb +7 -11
  17. data/lib/active_support/core_ext/array.rb +1 -1
  18. data/lib/active_support/core_ext/array/access.rb +18 -6
  19. data/lib/active_support/core_ext/array/extract.rb +21 -0
  20. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
  21. data/lib/active_support/core_ext/class/attribute.rb +11 -16
  22. data/lib/active_support/core_ext/class/subclasses.rb +1 -1
  23. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  24. data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -47
  25. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  26. data/lib/active_support/core_ext/enumerable.rb +97 -73
  27. data/lib/active_support/core_ext/hash.rb +1 -2
  28. data/lib/active_support/core_ext/hash/compact.rb +2 -26
  29. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  30. data/lib/active_support/core_ext/hash/except.rb +1 -1
  31. data/lib/active_support/core_ext/hash/keys.rb +0 -29
  32. data/lib/active_support/core_ext/hash/slice.rb +3 -25
  33. data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
  34. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  35. data/lib/active_support/core_ext/kernel.rb +0 -1
  36. data/lib/active_support/core_ext/load_error.rb +1 -1
  37. data/lib/active_support/core_ext/module.rb +0 -1
  38. data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -10
  39. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +13 -19
  40. data/lib/active_support/core_ext/module/delegation.rb +33 -7
  41. data/lib/active_support/core_ext/module/introspection.rb +37 -13
  42. data/lib/active_support/core_ext/module/reachable.rb +1 -6
  43. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  44. data/lib/active_support/core_ext/numeric.rb +0 -1
  45. data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
  46. data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
  47. data/lib/active_support/core_ext/object/blank.rb +1 -2
  48. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  49. data/lib/active_support/core_ext/object/json.rb +1 -0
  50. data/lib/active_support/core_ext/object/try.rb +15 -7
  51. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  52. data/lib/active_support/core_ext/range/compare_range.rb +22 -13
  53. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  54. data/lib/active_support/core_ext/range/include_range.rb +6 -0
  55. data/lib/active_support/core_ext/regexp.rb +0 -4
  56. data/lib/active_support/core_ext/securerandom.rb +23 -3
  57. data/lib/active_support/core_ext/string/access.rb +8 -0
  58. data/lib/active_support/core_ext/string/filters.rb +42 -1
  59. data/lib/active_support/core_ext/string/inflections.rb +7 -2
  60. data/lib/active_support/core_ext/string/multibyte.rb +4 -3
  61. data/lib/active_support/core_ext/string/output_safety.rb +61 -5
  62. data/lib/active_support/core_ext/string/strip.rb +3 -1
  63. data/lib/active_support/core_ext/time/calculations.rb +31 -2
  64. data/lib/active_support/core_ext/uri.rb +1 -0
  65. data/lib/active_support/current_attributes.rb +8 -0
  66. data/lib/active_support/dependencies.rb +69 -16
  67. data/lib/active_support/dependencies/zeitwerk_integration.rb +110 -0
  68. data/lib/active_support/deprecation.rb +1 -1
  69. data/lib/active_support/deprecation/behaviors.rb +1 -1
  70. data/lib/active_support/deprecation/method_wrappers.rb +8 -20
  71. data/lib/active_support/deprecation/proxy_wrappers.rb +24 -5
  72. data/lib/active_support/descendants_tracker.rb +56 -9
  73. data/lib/active_support/duration.rb +4 -3
  74. data/lib/active_support/duration/iso8601_parser.rb +2 -3
  75. data/lib/active_support/duration/iso8601_serializer.rb +3 -4
  76. data/lib/active_support/encrypted_configuration.rb +0 -4
  77. data/lib/active_support/encrypted_file.rb +2 -1
  78. data/lib/active_support/evented_file_update_checker.rb +39 -9
  79. data/lib/active_support/execution_wrapper.rb +1 -0
  80. data/lib/active_support/gem_version.rb +4 -4
  81. data/lib/active_support/hash_with_indifferent_access.rb +22 -18
  82. data/lib/active_support/i18n.rb +1 -0
  83. data/lib/active_support/i18n_railtie.rb +9 -1
  84. data/lib/active_support/inflector/inflections.rb +1 -4
  85. data/lib/active_support/inflector/methods.rb +15 -27
  86. data/lib/active_support/inflector/transliterate.rb +47 -18
  87. data/lib/active_support/json/decoding.rb +23 -23
  88. data/lib/active_support/json/encoding.rb +6 -2
  89. data/lib/active_support/key_generator.rb +0 -32
  90. data/lib/active_support/lazy_load_hooks.rb +5 -1
  91. data/lib/active_support/locale/en.rb +31 -0
  92. data/lib/active_support/log_subscriber.rb +31 -8
  93. data/lib/active_support/logger.rb +0 -15
  94. data/lib/active_support/logger_silence.rb +28 -12
  95. data/lib/active_support/logger_thread_safe_level.rb +26 -4
  96. data/lib/active_support/message_encryptor.rb +3 -5
  97. data/lib/active_support/message_verifier.rb +3 -3
  98. data/lib/active_support/multibyte/chars.rb +29 -48
  99. data/lib/active_support/multibyte/unicode.rb +44 -281
  100. data/lib/active_support/notifications.rb +41 -4
  101. data/lib/active_support/notifications/fanout.rb +98 -13
  102. data/lib/active_support/notifications/instrumenter.rb +79 -8
  103. data/lib/active_support/number_helper.rb +7 -0
  104. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -2
  105. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
  106. data/lib/active_support/number_helper/number_to_human_converter.rb +3 -1
  107. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -1
  108. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  109. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -0
  110. data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -3
  111. data/lib/active_support/ordered_options.rb +1 -1
  112. data/lib/active_support/parameter_filter.rb +129 -0
  113. data/lib/active_support/rails.rb +0 -6
  114. data/lib/active_support/reloader.rb +4 -5
  115. data/lib/active_support/security_utils.rb +1 -1
  116. data/lib/active_support/subscriber.rb +65 -26
  117. data/lib/active_support/tagged_logging.rb +13 -4
  118. data/lib/active_support/test_case.rb +91 -0
  119. data/lib/active_support/testing/assertions.rb +15 -1
  120. data/lib/active_support/testing/deprecation.rb +0 -1
  121. data/lib/active_support/testing/file_fixtures.rb +2 -0
  122. data/lib/active_support/testing/isolation.rb +2 -2
  123. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  124. data/lib/active_support/testing/parallelization.rb +128 -0
  125. data/lib/active_support/testing/stream.rb +1 -1
  126. data/lib/active_support/testing/time_helpers.rb +7 -7
  127. data/lib/active_support/time_with_zone.rb +15 -5
  128. data/lib/active_support/values/time_zone.rb +12 -7
  129. data/lib/active_support/xml_mini.rb +2 -9
  130. data/lib/active_support/xml_mini/jdom.rb +2 -2
  131. data/lib/active_support/xml_mini/libxml.rb +2 -2
  132. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  133. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  134. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  135. data/lib/active_support/xml_mini/rexml.rb +2 -2
  136. metadata +34 -9
  137. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  138. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/regexp"
4
-
5
3
  module ActiveSupport
6
4
  class Deprecation
7
5
  class DeprecationProxy #:nodoc:
@@ -122,7 +120,14 @@ module ActiveSupport
122
120
  # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
123
121
  # (Backtrace information…)
124
122
  # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
125
- class DeprecatedConstantProxy < DeprecationProxy
123
+ class DeprecatedConstantProxy < Module
124
+ def self.new(*args, &block)
125
+ object = args.first
126
+
127
+ return object unless object
128
+ super
129
+ end
130
+
126
131
  def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
127
132
  require "active_support/inflector/methods"
128
133
 
@@ -132,6 +137,14 @@ module ActiveSupport
132
137
  @message = message
133
138
  end
134
139
 
140
+ instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
141
+
142
+ # Don't give a deprecation warning on inspect since test/unit and error
143
+ # logs rely on it for diagnostics.
144
+ def inspect
145
+ target.inspect
146
+ end
147
+
135
148
  # Returns the class of the new constant.
136
149
  #
137
150
  # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
@@ -146,8 +159,14 @@ module ActiveSupport
146
159
  ActiveSupport::Inflector.constantize(@new_const.to_s)
147
160
  end
148
161
 
149
- def warn(callstack, called, args)
150
- @deprecator.warn(@message, callstack)
162
+ def const_missing(name)
163
+ @deprecator.warn(@message, caller_locations)
164
+ target.const_get(name)
165
+ end
166
+
167
+ def method_missing(called, *args, &block)
168
+ @deprecator.warn(@message, caller_locations)
169
+ target.__send__(called, *args, &block)
151
170
  end
152
171
  end
153
172
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "weakref"
4
+
3
5
  module ActiveSupport
4
6
  # This module provides an internal implementation to track descendants
5
7
  # which is faster than iterating through ObjectSpace.
@@ -8,7 +10,8 @@ module ActiveSupport
8
10
 
9
11
  class << self
10
12
  def direct_descendants(klass)
11
- @@direct_descendants[klass] || []
13
+ descendants = @@direct_descendants[klass]
14
+ descendants ? descendants.to_a : []
12
15
  end
13
16
 
14
17
  def descendants(klass)
@@ -20,10 +23,10 @@ module ActiveSupport
20
23
  def clear
21
24
  if defined? ActiveSupport::Dependencies
22
25
  @@direct_descendants.each do |klass, descendants|
23
- if ActiveSupport::Dependencies.autoloaded?(klass)
26
+ if Dependencies.autoloaded?(klass)
24
27
  @@direct_descendants.delete(klass)
25
28
  else
26
- descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) }
29
+ descendants.reject! { |v| Dependencies.autoloaded?(v) }
27
30
  end
28
31
  end
29
32
  else
@@ -34,16 +37,19 @@ module ActiveSupport
34
37
  # This is the only method that is not thread safe, but is only ever called
35
38
  # during the eager loading phase.
36
39
  def store_inherited(klass, descendant)
37
- (@@direct_descendants[klass] ||= []) << descendant
40
+ (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
38
41
  end
39
42
 
40
43
  private
41
- def accumulate_descendants(klass, acc)
42
- if direct_descendants = @@direct_descendants[klass]
43
- acc.concat(direct_descendants)
44
- direct_descendants.each { |direct_descendant| accumulate_descendants(direct_descendant, acc) }
44
+
45
+ def accumulate_descendants(klass, acc)
46
+ if direct_descendants = @@direct_descendants[klass]
47
+ direct_descendants.each do |direct_descendant|
48
+ acc << direct_descendant
49
+ accumulate_descendants(direct_descendant, acc)
50
+ end
51
+ end
45
52
  end
46
- end
47
53
  end
48
54
 
49
55
  def inherited(base)
@@ -58,5 +64,46 @@ module ActiveSupport
58
64
  def descendants
59
65
  DescendantsTracker.descendants(self)
60
66
  end
67
+
68
+ # DescendantsArray is an array that contains weak references to classes.
69
+ class DescendantsArray # :nodoc:
70
+ include Enumerable
71
+
72
+ def initialize
73
+ @refs = []
74
+ end
75
+
76
+ def initialize_copy(orig)
77
+ @refs = @refs.dup
78
+ end
79
+
80
+ def <<(klass)
81
+ cleanup!
82
+ @refs << WeakRef.new(klass)
83
+ end
84
+
85
+ def each
86
+ @refs.each do |ref|
87
+ yield ref.__getobj__
88
+ rescue WeakRef::RefError
89
+ end
90
+ end
91
+
92
+ def refs_size
93
+ @refs.size
94
+ end
95
+
96
+ def cleanup!
97
+ @refs.delete_if { |ref| !ref.weakref_alive? }
98
+ end
99
+
100
+ def reject!
101
+ @refs.reject! do |ref|
102
+ yield ref.__getobj__
103
+ rescue WeakRef::RefError
104
+ true
105
+ end
106
+ end
107
+ end
61
108
  end
62
109
  end
@@ -4,7 +4,6 @@ require "active_support/core_ext/array/conversions"
4
4
  require "active_support/core_ext/module/delegation"
5
5
  require "active_support/core_ext/object/acts_like"
6
6
  require "active_support/core_ext/string/filters"
7
- require "active_support/deprecation"
8
7
 
9
8
  module ActiveSupport
10
9
  # Provides accurate date and time measurements using Date#advance and
@@ -214,8 +213,11 @@ module ActiveSupport
214
213
  end
215
214
 
216
215
  def coerce(other) #:nodoc:
217
- if Scalar === other
216
+ case other
217
+ when Scalar
218
218
  [other, self]
219
+ when Duration
220
+ [Scalar.new(other.value), self]
219
221
  else
220
222
  [Scalar.new(other), self]
221
223
  end
@@ -373,7 +375,6 @@ module ActiveSupport
373
375
  return "0 seconds" if parts.empty?
374
376
 
375
377
  parts.
376
- reduce(::Hash.new(0)) { |h, (l, r)| h[l] += r; h }.
377
378
  sort_by { |unit, _ | PARTS.index(unit) }.
378
379
  map { |unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}" }.
379
380
  to_sentence(locale: ::I18n.default_locale)
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "strscan"
4
- require "active_support/core_ext/regexp"
5
4
 
6
5
  module ActiveSupport
7
6
  class Duration
@@ -14,8 +13,8 @@ module ActiveSupport
14
13
  class ParsingError < ::ArgumentError; end
15
14
 
16
15
  PERIOD_OR_COMMA = /\.|,/
17
- PERIOD = ".".freeze
18
- COMMA = ",".freeze
16
+ PERIOD = "."
17
+ COMMA = ","
19
18
 
20
19
  SIGN_MARKER = /\A\-|\+|/
21
20
  DATE_MARKER = /P/
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/blank"
4
- require "active_support/core_ext/hash/transform_values"
5
4
 
6
5
  module ActiveSupport
7
6
  class Duration
@@ -15,14 +14,14 @@ module ActiveSupport
15
14
  # Builds and returns output string.
16
15
  def serialize
17
16
  parts, sign = normalize
18
- return "PT0S".freeze if parts.empty?
17
+ return "PT0S" if parts.empty?
19
18
 
20
- output = "P".dup
19
+ output = +"P"
21
20
  output << "#{parts[:years]}Y" if parts.key?(:years)
22
21
  output << "#{parts[:months]}M" if parts.key?(:months)
23
22
  output << "#{parts[:weeks]}W" if parts.key?(:weeks)
24
23
  output << "#{parts[:days]}D" if parts.key?(:days)
25
- time = "".dup
24
+ time = +""
26
25
  time << "#{parts[:hours]}H" if parts.key?(:hours)
27
26
  time << "#{parts[:minutes]}M" if parts.key?(:minutes)
28
27
  if parts.key?(:seconds)
@@ -38,10 +38,6 @@ module ActiveSupport
38
38
  @options ||= ActiveSupport::InheritableOptions.new(config)
39
39
  end
40
40
 
41
- def serialize(config)
42
- config.present? ? YAML.dump(config) : ""
43
- end
44
-
45
41
  def deserialize(config)
46
42
  YAML.load(config).presence || {}
47
43
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require "tmpdir"
4
5
  require "active_support/message_encryptor"
5
6
 
6
7
  module ActiveSupport
@@ -67,7 +68,7 @@ module ActiveSupport
67
68
 
68
69
  write(updated_contents) if updated_contents != contents
69
70
  ensure
70
- FileUtils.rm(tmp_path) if tmp_path.exist?
71
+ FileUtils.rm(tmp_path) if tmp_path&.exist?
71
72
  end
72
73
 
73
74
 
@@ -52,16 +52,17 @@ module ActiveSupport
52
52
  @pid = Process.pid
53
53
  @boot_mutex = Mutex.new
54
54
 
55
- if (@dtw = directories_to_watch).any?
55
+ dtw = directories_to_watch
56
+ @dtw, @missing = dtw.partition(&:exist?)
57
+
58
+ if @dtw.any?
56
59
  # Loading listen triggers warnings. These are originated by a legit
57
60
  # usage of attr_* macros for private attributes, but adds a lot of noise
58
61
  # to our test suite. Thus, we lazy load it and disable warnings locally.
59
62
  silence_warnings do
60
- begin
61
- require "listen"
62
- rescue LoadError => e
63
- raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
64
- end
63
+ require "listen"
64
+ rescue LoadError => e
65
+ raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
65
66
  end
66
67
  end
67
68
  boot!
@@ -75,6 +76,19 @@ module ActiveSupport
75
76
  @updated.make_true
76
77
  end
77
78
  end
79
+
80
+ if @missing.any?(&:exist?)
81
+ @boot_mutex.synchronize do
82
+ appeared, @missing = @missing.partition(&:exist?)
83
+ shutdown!
84
+
85
+ @dtw += appeared
86
+ boot!
87
+
88
+ @updated.make_true
89
+ end
90
+ end
91
+
78
92
  @updated.true?
79
93
  end
80
94
 
@@ -93,7 +107,21 @@ module ActiveSupport
93
107
 
94
108
  private
95
109
  def boot!
96
- Listen.to(*@dtw, &method(:changed)).start
110
+ normalize_dirs!
111
+
112
+ unless @dtw.empty?
113
+ Listen.to(*@dtw, &method(:changed)).start
114
+ end
115
+ end
116
+
117
+ def shutdown!
118
+ Listen.stop
119
+ end
120
+
121
+ def normalize_dirs!
122
+ @dirs.transform_keys! do |dir|
123
+ dir.exist? ? dir.realpath : dir
124
+ end
97
125
  end
98
126
 
99
127
  def changed(modified, added, removed)
@@ -113,7 +141,9 @@ module ActiveSupport
113
141
  ext = @ph.normalize_extension(file.extname)
114
142
 
115
143
  file.dirname.ascend do |dir|
116
- if @dirs.fetch(dir, []).include?(ext)
144
+ matching = @dirs[dir]
145
+
146
+ if matching && (matching.empty? || matching.include?(ext))
117
147
  break true
118
148
  elsif dir == @lcsp || dir.root?
119
149
  break false
@@ -123,7 +153,7 @@ module ActiveSupport
123
153
  end
124
154
 
125
155
  def directories_to_watch
126
- dtw = (@files + @dirs.keys).map { |f| @ph.existing_parent(f) }
156
+ dtw = @files.map(&:dirname) + @dirs.keys
127
157
  dtw.compact!
128
158
  dtw.uniq!
129
159
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/callbacks"
4
+ require "concurrent/hash"
4
5
 
5
6
  module ActiveSupport
6
7
  class ExecutionWrapper
@@ -7,10 +7,10 @@ module ActiveSupport
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 5
11
- MINOR = 2
12
- TINY = 4
13
- PRE = "4"
10
+ MAJOR = 6
11
+ MINOR = 0
12
+ TINY = 0
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -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
@@ -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
  #
@@ -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
@@ -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__)