Skip to content
Browse files

HashWithIndifferentAccess shouldn't confuse false and nil. Closes #5601

…. Nor should it mistreat legitimate nil values.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4555 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent c51f9fd commit 12600d77dd1757365dc86e6aec5cafb48ec49886 @jeremy jeremy committed Jul 5, 2006
View
2 activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* HashWithIndifferentAccess shouldn't confuse false and nil. #5601 [shugo@ruby-lang.org]
+
* Fixed HashWithIndifferentAccess#default #5586 [chris@seagul.co.uk]
* More compatible Hash.create_from_xml. #5523 [nunemaker@gmail.com]
View
17 activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
@@ -10,15 +10,18 @@ def initialize(constructor = {})
super(constructor)
end
end
-
+
def default(key = nil)
- value = self[key.to_s] if key.is_a?(Symbol)
- value ? value : super
+ if key.is_a?(Symbol) && include?(key = key.to_s)
+ self[key]
+ else
+ super
+ end
end
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
alias_method :regular_update, :update unless method_defined?(:regular_update)
-
+
def []=(key, value)
regular_writer(convert_key(key), convert_value(value))
end
@@ -27,7 +30,7 @@ def update(other_hash)
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
self
end
-
+
alias_method :merge!, :update
def key?(key)
@@ -49,7 +52,7 @@ def values_at(*indices)
def dup
HashWithIndifferentAccess.new(self)
end
-
+
def merge(hash)
self.dup.update(hash)
end
@@ -60,7 +63,7 @@ def delete(key)
def stringify_keys!; self end
def symbolize_keys!; self end
-
+
protected
def convert_key(key)
key.kind_of?(Symbol) ? key.to_s : key
View
89 activesupport/test/core_ext/hash_ext_test.rb
@@ -50,18 +50,18 @@ def test_indifferent_assorted
@strings = @strings.with_indifferent_access
@symbols = @symbols.with_indifferent_access
@mixed = @mixed.with_indifferent_access
-
+
assert_equal 'a', @strings.send(:convert_key, :a)
-
+
assert_equal 1, @strings.fetch('a')
assert_equal 1, @strings.fetch(:a.to_s)
assert_equal 1, @strings.fetch(:a)
-
+
hashes = { :@strings => @strings, :@symbols => @symbols, :@mixed => @mixed }
method_map = { :'[]' => 1, :fetch => 1, :values_at => [1],
:has_key? => true, :include? => true, :key? => true,
:member? => true }
-
+
hashes.each do |name, hash|
method_map.sort_by { |m| m.to_s }.each do |meth, expected|
assert_equal(expected, hash.send(meth, 'a'),
@@ -70,21 +70,49 @@ def test_indifferent_assorted
"Calling #{name}.#{meth} :a")
end
end
-
+
assert_equal [1, 2], @strings.values_at('a', 'b')
assert_equal [1, 2], @strings.values_at(:a, :b)
assert_equal [1, 2], @symbols.values_at('a', 'b')
assert_equal [1, 2], @symbols.values_at(:a, :b)
assert_equal [1, 2], @mixed.values_at('a', 'b')
assert_equal [1, 2], @mixed.values_at(:a, :b)
end
-
+
+ def test_indifferent_reading
+ hash = HashWithIndifferentAccess.new
+ hash["a"] = 1
+ hash["b"] = true
+ hash["c"] = false
+ hash["d"] = nil
+
+ assert_equal 1, hash[:a]
+ assert_equal true, hash[:b]
+ assert_equal false, hash[:c]
+ assert_equal nil, hash[:d]
+ assert_equal nil, hash[:e]
+ end
+
+ def test_indifferent_reading_with_nonnil_default
+ hash = HashWithIndifferentAccess.new(1)
+ hash["a"] = 1
+ hash["b"] = true
+ hash["c"] = false
+ hash["d"] = nil
+
+ assert_equal 1, hash[:a]
+ assert_equal true, hash[:b]
+ assert_equal false, hash[:c]
+ assert_equal nil, hash[:d]
+ assert_equal 1, hash[:e]
+ end
+
def test_indifferent_writing
hash = HashWithIndifferentAccess.new
hash[:a] = 1
hash['b'] = 2
hash[3] = 3
-
+
assert_equal hash['a'], 1
assert_equal hash['b'], 2
assert_equal hash[:a], 1
@@ -96,7 +124,7 @@ def test_indifferent_update
hash = HashWithIndifferentAccess.new
hash[:a] = 'a'
hash['b'] = 'b'
-
+
updated_with_strings = hash.update(@strings)
updated_with_symbols = hash.update(@symbols)
updated_with_mixed = hash.update(@mixed)
@@ -119,21 +147,21 @@ def test_indifferent_merging
hash = HashWithIndifferentAccess.new
hash[:a] = 'failure'
hash['b'] = 'failure'
-
+
other = { 'a' => 1, :b => 2 }
-
+
merged = hash.merge(other)
-
+
assert_equal HashWithIndifferentAccess, merged.class
assert_equal 1, merged[:a]
assert_equal 2, merged['b']
-
+
hash.update(other)
-
+
assert_equal 1, hash[:a]
assert_equal 2, hash['b']
end
-
+
def test_indifferent_deleting
get_hash = proc{ { :a => 'foo' }.with_indifferent_access }
hash = get_hash.call
@@ -160,7 +188,7 @@ def test_assert_valid_keys
{ :failure => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ])
{ :failure => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny)
end
-
+
assert_raises(ArgumentError, "Unknown key(s): failore") do
{ :failore => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ])
{ :failore => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny)
@@ -170,7 +198,7 @@ def test_assert_valid_keys
def test_indifferent_subhashes
h = {'user' => {'id' => 5}}.with_indifferent_access
['user', :user].each {|user| [:id, 'id'].each {|id| assert_equal 5, h[user][id], "h[#{user.inspect}][#{id.inspect}] should be 5"}}
-
+
h = {:user => {:id => 5}}.with_indifferent_access
['user', :user].each {|user| [:id, 'id'].each {|id| assert_equal 5, h[user][id], "h[#{user.inspect}][#{id.inspect}] should be 5"}}
end
@@ -265,7 +293,7 @@ def test_two_levels_with_second_level_overriding_to_xml
assert xml.include?(%(<address><street>Paulina</street></address>))
assert xml.include?(%(<level_one><second_level>content</second_level></level_one>))
end
-
+
def test_two_levels_with_array
xml = { :name => "David", :addresses => [{ :street => "Paulina" }, { :street => "Evergreen" }] }.to_xml(@xml_options)
assert_equal "<person>", xml.first(8)
@@ -274,7 +302,7 @@ def test_two_levels_with_array
assert xml.include?(%(<address><street>Evergreen</street></address>))
assert xml.include?(%(<name>David</name>))
end
-
+
def test_three_levels_with_array
xml = { :name => "David", :addresses => [{ :streets => [ { :name => "Paulina" }, { :name => "Paulina" } ] } ] }.to_xml(@xml_options)
assert xml.include?(%(<addresses><address><streets><street><name>))
@@ -295,7 +323,7 @@ def test_single_record_from_xml
<parent-id></parent-id>
</topic>
EOT
-
+
expected_topic_hash = {
:title => "The First Topic",
:author_name => "David",
@@ -308,7 +336,7 @@ def test_single_record_from_xml
:author_email_address => "david@loudthinking.com",
:parent_id => nil
}.stringify_keys
-
+
assert_equal expected_topic_hash, Hash.create_from_xml(topic_xml)["topic"]
end
@@ -341,7 +369,7 @@ def test_multiple_records_from_xml
</topic>
</topics>
EOT
-
+
expected_topic_hash = {
:title => "The First Topic",
:author_name => "David",
@@ -354,10 +382,10 @@ def test_multiple_records_from_xml
:author_email_address => "david@loudthinking.com",
:parent_id => nil
}.stringify_keys
-
+
assert_equal expected_topic_hash, Hash.create_from_xml(topics_xml)["topics"]["topic"].first
end
-
+
def test_single_record_from_xml_with_attributes_other_than_type
topic_xml = <<-EOT
<rsp stat="ok">
@@ -366,7 +394,7 @@ def test_single_record_from_xml_with_attributes_other_than_type
</photos>
</rsp>
EOT
-
+
expected_topic_hash = {
:id => "175756086",
:owner => "55569174@N00",
@@ -377,29 +405,28 @@ def test_single_record_from_xml_with_attributes_other_than_type
:isfriend => "0",
:isfamily => "0",
}.stringify_keys
-
+
assert_equal expected_topic_hash, Hash.create_from_xml(topic_xml)["rsp"]["photos"]["photo"]
end
-
+
def test_should_use_default_value_for_unknown_key
hash_wia = HashWithIndifferentAccess.new(3)
assert_equal 3, hash_wia[:new_key]
end
-
+
def test_should_use_default_value_if_no_key_is_supplied
hash_wia = HashWithIndifferentAccess.new(3)
assert_equal 3, hash_wia.default
end
-
+
def test_should_nil_if_no_default_value_is_supplied
hash_wia = HashWithIndifferentAccess.new
assert_nil hash_wia.default
end
-
+
def test_should_copy_the_default_value_when_converting_to_hash_with_indifferent_access
hash = Hash.new(3)
hash_wia = hash.with_indifferent_access
assert_equal 3, hash_wia.default
end
-
-end
+end

0 comments on commit 12600d7

Please sign in to comment.
Something went wrong with that request. Please try again.