diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 1927cddf34fa2caef8a4a470565706cb6b7df8db..8b34b8b28b87a025193b06c4816170a99c3eaad2 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -74,16 +74,6 @@ def initialize(constructor = {}) end end - def default(*args) - arg_key = args.first - - if include?(key = convert_key(arg_key)) - self[key] - else - super - end - end - def self.[](*args) new.merge!(Hash[*args]) end @@ -185,6 +175,36 @@ def fetch(key, *extras) super(convert_key(key), *extras) end + if Hash.new.respond_to?(:dig) + # Same as Hash#dig where the key passed as argument can be + # either a string or a symbol: + # + # counters = ActiveSupport::HashWithIndifferentAccess.new + # counters[:foo] = { bar: 1 } + # + # counters.dig('foo', 'bar') # => 1 + # counters.dig(:foo, :bar) # => 1 + # counters.dig(:zoo) # => nil + def dig(*args) + args[0] = convert_key(args[0]) if args.size > 0 + super(*args) + end + end + + # Same as Hash#default where the key passed as argument can be + # either a string or a symbol: + # + # hash = ActiveSupport::HashWithIndifferentAccess.new(1) + # hash.default # => 1 + # + # hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key } + # hash.default # => nil + # hash.default('foo') # => 'foo' + # hash.default(:foo) # => 'foo' + def default(*args) + super(*args.map { |arg| convert_key(arg) }) + end + # Returns an array of the values at the specified indices: # # hash = ActiveSupport::HashWithIndifferentAccess.new diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 525ea08abd08c7df366f728dad21330f7b3a2185..7777d0b1bc2688fd302f9fbd68db196e4ff93ec2 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -729,6 +729,32 @@ def test_nested_dig_indifferent_access assert_equal 1234, data.dig(:this, :views) end + def test_argless_default_with_existing_nil_key + h = Hash.new(:default).merge(nil => "defined").with_indifferent_access + + assert_equal :default, h.default + end + + def test_default_with_argument + h = Hash.new { 5 }.merge(1 => 2).with_indifferent_access + + assert_equal 5, h.default(1) + end + + def test_default_proc + h = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key } + + assert_nil h.default + assert_equal "foo", h.default("foo") + assert_equal "foo", h.default(:foo) + end + + def test_double_conversion_with_nil_key + h = { nil => "defined" }.with_indifferent_access.with_indifferent_access + + assert_equal nil, h[:undefined_key] + end + def test_assert_valid_keys assert_nothing_raised do { failure: "stuff", funny: "business" }.assert_valid_keys([ :failure, :funny ])