Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Hash#slice(*keys) returns a new hash with only the given keys. #slice…

…! replaces the hash with only the given keys. Works with HashWithIndifferentAccess also.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5726 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 86deb270953f9c5b62813d3e1938f33cc807bd7f 1 parent 05a5209
@jeremy jeremy authored
View
2  activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Hash#slice(*keys) returns a new hash with only the given keys. #slice! replaces the hash with only the given keys. Works with HashWithIndifferentAccess also. [Jeremy Kemper]
+
* HashWithIndifferentAccess#to_hash converts to a Hash with String keys and the same default value. [Jeremy Kemper]
* Fix remove_constant to correctly handle constant names of the form "::A::...". References #6720. [Nicholas Seckar]
View
9 activesupport/lib/active_support/core_ext/hash.rb
@@ -1,8 +1,6 @@
-require File.dirname(__FILE__) + '/hash/keys'
-require File.dirname(__FILE__) + '/hash/indifferent_access'
-require File.dirname(__FILE__) + '/hash/reverse_merge'
-require File.dirname(__FILE__) + '/hash/conversions'
-require File.dirname(__FILE__) + '/hash/diff'
+%w(keys indifferent_access reverse_merge conversions diff slice).each do |ext|
+ require "#{File.dirname(__FILE__)}/hash/#{ext}"
+end
class Hash #:nodoc:
include ActiveSupport::CoreExtensions::Hash::Keys
@@ -10,4 +8,5 @@ class Hash #:nodoc:
include ActiveSupport::CoreExtensions::Hash::ReverseMerge
include ActiveSupport::CoreExtensions::Hash::Conversions
include ActiveSupport::CoreExtensions::Hash::Diff
+ include ActiveSupport::CoreExtensions::Hash::Slice
end
View
28 activesupport/lib/active_support/core_ext/hash/slice.rb
@@ -0,0 +1,28 @@
+require 'set'
+
+module ActiveSupport #:nodoc:
+ module CoreExtensions #:nodoc:
+ module Hash #:nodoc:
+ # Slice a hash to include only the given keys. This is useful for
+ # limiting an options hash to valid keys before passing to a method:
+ #
+ # def search(criteria = {})
+ # assert_valid_keys(:mass, :velocity, :time)
+ # end
+ #
+ # search(options.slice(:mass, :velocity, :time))
+ module Slice
+ # Returns a new hash with only the given keys.
+ def slice(*keys)
+ allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
+ reject { |key,| !allowed.include?(key) }
+ end
+
+ # Replaces the hash with only the given keys.
+ def slice!(*keys)
+ replace(slice(*keys))
+ end
+ end
+ end
+ end
+end
View
29 activesupport/test/core_ext/hash_ext_test.rb
@@ -243,6 +243,35 @@ def test_reverse_merge
def test_diff
assert_equal({ :a => 2 }, { :a => 2, :b => 5 }.diff({ :a => 1, :b => 5 }))
end
+
+ def test_slice
+ original = { :a => 'x', :b => 'y', :c => 10 }
+ expected = { :a => 'x', :b => 'y' }
+
+ # Should return a new hash with only the given keys.
+ assert_equal expected, original.slice(:a, :b)
+ assert_not_equal expected, original
+
+ # Should replace the hash with only the given 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
+
+ [['a', 'b'], [:a, :b]].each do |keys|
+ # Should return a new hash with only the given keys.
+ assert_equal expected, original.slice(*keys), keys.inspect
+ assert_not_equal expected, original
+
+ # Should replace the hash with only the given keys.
+ copy = original.dup
+ assert_equal expected, copy.slice!(*keys)
+ assert_equal expected, copy
+ end
+ end
end
class IWriteMyOwnXML
Please sign in to comment.
Something went wrong with that request. Please try again.