Permalink
Browse files

Hash#slice supports an array of keys [#613 state:resolved]

Signed-off-by: Joshua Peek <josh@joshpeek.com>
  • Loading branch information...
1 parent 7ae2105 commit 396f9df8916b71f83aad8d56559cf55fc8501679 @queso queso committed with josh Jul 17, 2008
@@ -12,6 +12,7 @@ module Hash #:nodoc:
module Slice
# Returns a new hash with only the given keys.
def slice(*keys)
+ keys.flatten!
keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
hash = {}
keys.each { |k| hash[k] = self[k] if has_key?(k) }
@@ -282,6 +282,20 @@ def test_slice
assert_equal expected, original
end
+ # This is needed for something like hash.slice!(hash.keys.sort_by {rand} [0..4])
+ def test_slice_with_array_keys
+ original = { :a => 'x', :b => 'y', :c => 10 }
+ expected = { :a => 'x', :b => 'y' }
+
+ # Should return a new hash with only the given keys, when given an array of keys.
+ assert_equal expected, original.slice([:a, :b])
+ assert_not_equal expected, original
+
+ # Should replace the hash with only the given keys, when given an array of keys.
+ assert_equal expected, original.slice!([:a, :b])
+ assert_equal expected, original
+ end
+
def test_indifferent_slice
original = { :a => 'x', :b => 'y', :c => 10 }.with_indifferent_access
expected = { :a => 'x', :b => 'y' }.with_indifferent_access
@@ -469,12 +483,12 @@ def test_single_record_from_xml_with_nil_values
EOT
expected_topic_hash = {
- :title => nil,
+ :title => nil,
:id => nil,
:approved => nil,
:written_on => nil,
:viewed_at => nil,
- :content => nil,
+ :content => nil,
:parent_id => nil
}.stringify_keys
@@ -552,7 +566,7 @@ def test_single_record_from_xml_with_attributes_other_than_type
assert_equal expected_topic_hash, Hash.from_xml(topic_xml)["rsp"]["photos"]["photo"]
end
-
+
def test_empty_array_from_xml
blog_xml = <<-XML
<blog>
@@ -650,13 +664,13 @@ def test_xsd_like_types_from_xml
assert_equal expected_bacon_hash, Hash.from_xml(bacon_xml)["bacon"]
end
-
+
def test_type_trickles_through_when_unknown
product_xml = <<-EOT
<product>
<weight type="double">0.5</weight>
<image type="ProductImage"><filename>image.gif</filename></image>
-
+
</product>
EOT
@@ -665,7 +679,7 @@ def test_type_trickles_through_when_unknown
:image => {'type' => 'ProductImage', 'filename' => 'image.gif' },
}.stringify_keys
- assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"]
+ assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"]
end
def test_should_use_default_value_for_unknown_key
@@ -699,41 +713,41 @@ def test_kernel_method_names_to_xml
assert_equal expected, hash.to_xml(@xml_options)
end
end
-
- def test_empty_string_works_for_typecast_xml_value
+
+ def test_empty_string_works_for_typecast_xml_value
assert_nothing_raised do
Hash.send!(:typecast_xml_value, "")
end
end
-
+
def test_escaping_to_xml
- hash = {
- :bare_string => 'First & Last Name',
+ hash = {
+ :bare_string => 'First & Last Name',
:pre_escaped_string => 'First &amp; Last Name'
}.stringify_keys
-
+
expected_xml = '<person><bare-string>First &amp; Last Name</bare-string><pre-escaped-string>First &amp;amp; Last Name</pre-escaped-string></person>'
assert_equal expected_xml, hash.to_xml(@xml_options)
end
-
+
def test_unescaping_from_xml
xml_string = '<person><bare-string>First &amp; Last Name</bare-string><pre-escaped-string>First &amp;amp; Last Name</pre-escaped-string></person>'
- expected_hash = {
- :bare_string => 'First & Last Name',
+ expected_hash = {
+ :bare_string => 'First & Last Name',
:pre_escaped_string => 'First &amp; Last Name'
}.stringify_keys
assert_equal expected_hash, Hash.from_xml(xml_string)['person']
end
-
+
def test_roundtrip_to_xml_from_xml
- hash = {
- :bare_string => 'First & Last Name',
+ hash = {
+ :bare_string => 'First & Last Name',
:pre_escaped_string => 'First &amp; Last Name'
}.stringify_keys
assert_equal hash, Hash.from_xml(hash.to_xml(@xml_options))['person']
end
-
+
def test_datetime_xml_type_with_utc_time
alert_xml = <<-XML
<alert>
@@ -744,7 +758,7 @@ def test_datetime_xml_type_with_utc_time
assert alert_at.utc?
assert_equal Time.utc(2008, 2, 10, 15, 30, 45), alert_at
end
-
+
def test_datetime_xml_type_with_non_utc_time
alert_xml = <<-XML
<alert>
@@ -755,7 +769,7 @@ def test_datetime_xml_type_with_non_utc_time
assert alert_at.utc?
assert_equal Time.utc(2008, 2, 10, 15, 30, 45), alert_at
end
-
+
def test_datetime_xml_type_with_far_future_date
alert_xml = <<-XML
<alert>

5 comments on commit 396f9df

Contributor

skojin replied Jul 17, 2008

That will broke behavior when I use array as key
original = {[5, 6] => ‘x’, [2, 3] => ‘y’, [1, 6] => 10 }

I think people can always use original.slice(*[:a, :b])

Member

josh replied Jul 17, 2008

Could do Array(…) instead of flatten. I think that would work for both cases. Submit a patch to Lighthouse and I’ll have a look.

Contributor

matthewrudy replied Jul 17, 2008

Yeah,
I think this is crap.

if you have an array
you should just splat it.

if you legitimately give it an array as a key
it should be allowed

Contributor

tomafro replied Jul 17, 2008

What sergey and matthew said. The implicit assumption that arrays aren’t used as keys within hashes is incorrect. The original implementation of slice was correct.

Contributor

matthewrudy replied Jul 17, 2008

I’ve added a test to assert the original behaviour (added to the original ticket)
http://rails.lighthouseapp.com/projects/8994/tickets/613-slice-and-slice-don-t-accept-an-array-of-keys#ticket-613-6

Please sign in to comment.