diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index be7eba5b0c58ad4dc996948850ebab057da4baac..fe243d4abf1fb1a042d5c6650b27c1164a2652a0 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Added Hash#except which is the inverse of Hash#slice -- return the hash except the keys that are specified [DHH] + * Added support for pluralization with a different starting letter than the singular version (cow/kine) #4929 [norri_b/hasmanyjosh] * Demote Hash#to_xml to use XmlSimple#xml_in_string so it can't read files or stdin. #8453 [candlerb, Jeremy Kemper] diff --git a/activesupport/lib/active_support/core_ext/hash.rb b/activesupport/lib/active_support/core_ext/hash.rb index 2a99468b4e9ecad51ac734cd938e33fdf1b2496f..b805d2da62220994e3f98bf62a022ccf4e692f2c 100644 --- a/activesupport/lib/active_support/core_ext/hash.rb +++ b/activesupport/lib/active_support/core_ext/hash.rb @@ -1,4 +1,4 @@ -%w(keys indifferent_access reverse_merge conversions diff slice).each do |ext| +%w(keys indifferent_access reverse_merge conversions diff slice except).each do |ext| require "#{File.dirname(__FILE__)}/hash/#{ext}" end @@ -9,4 +9,5 @@ class Hash #:nodoc: include ActiveSupport::CoreExtensions::Hash::Conversions include ActiveSupport::CoreExtensions::Hash::Diff include ActiveSupport::CoreExtensions::Hash::Slice + include ActiveSupport::CoreExtensions::Hash::Except end diff --git a/activesupport/lib/active_support/core_ext/hash/except.rb b/activesupport/lib/active_support/core_ext/hash/except.rb new file mode 100644 index 0000000000000000000000000000000000000000..8362cd880e4fc505c3067be2758464c83b2029a4 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/hash/except.rb @@ -0,0 +1,24 @@ +require 'set' + +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Hash #:nodoc: + # Return a hash that includes everything but the given keys. This is useful for + # limiting a set of parameters to everything but a few known toggles: + # + # @person.update_attributes(params[:person].except(:admin)) + module Except + # Returns a new hash without the given keys. + def except(*keys) + rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys) + reject { |key,| rejected.include?(key) } + end + + # Replaces the hash without only the given keys. + def except!(*keys) + replace(except(*keys)) + end + end + end + end +end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index cae19a9335e707fbd59a85bf64fa0d1b72f62254..c2b7a7f1eb6102a282d9ec1e996bc96fc02d5308 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -277,6 +277,19 @@ def test_indifferent_slice assert_equal expected, copy end end + + def test_except + 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.except(:c) + assert_not_equal expected, original + + # Should replace the hash with only the given keys. + assert_equal expected, original.except!(:c) + assert_equal expected, original + end end class IWriteMyOwnXML