aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/slice.rb16
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb32
3 files changed, 50 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 307cc7f405..78978ac981 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Adding Hash#without Closes #7369 [eventualbuddha]
+
* TimeWithZone#method_missing: send to utc to advance with dst correctness, otherwise send to time. Adding tests for time calculations methods [Geoff Buesing]
* Add config.active_support.use_standard_json_time_format setting so that Times and Dates export to ISO 8601 dates. [rick]
diff --git a/activesupport/lib/active_support/core_ext/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb
index 6fe5e05330..c270e3906b 100644
--- a/activesupport/lib/active_support/core_ext/hash/slice.rb
+++ b/activesupport/lib/active_support/core_ext/hash/slice.rb
@@ -11,6 +11,11 @@ module ActiveSupport #:nodoc:
# end
#
# search(options.slice(:mass, :velocity, :time))
+ #
+ # Also allows leaving out certain keys. This is useful when duplicating
+ # a hash but omitting a certain subset:
+ #
+ # Event.new(event.attributes.without(:id, :user_id))
module Slice
# Returns a new hash with only the given keys.
def slice(*keys)
@@ -22,6 +27,17 @@ module ActiveSupport #:nodoc:
def slice!(*keys)
replace(slice(*keys))
end
+
+ # Returns a new hash without the given keys.
+ def without(*keys)
+ allowed = self.keys - (respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
+ slice(*allowed)
+ end
+
+ # Replaces the hash without the given keys.
+ def without!(*keys)
+ replace(without(*keys))
+ 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 706e218abc..9d1d6ec33f 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -310,6 +310,38 @@ class HashExtTest < Test::Unit::TestCase
assert_equal expected, original.except!(:c)
assert_equal expected, original
end
+
+ def test_without
+ original = { :a => 'x', :b => 'y', :c => 10 }
+ expected = { :a => 'x' }
+
+ # Should return a hash without the given keys.
+ assert_equal expected, original.without(:b, :c)
+ assert_not_equal expected, original
+
+ # Should ignore non-existant keys.
+ assert_equal expected, original.without(:b, :c, :d)
+
+ # Should replace the hash with the given keys taken away.
+ assert_equal expected, original.without!(:b, :c)
+ assert_equal expected, original
+ end
+
+ def test_indifferent_without
+ original = { :a => 'x', :b => 'y', :c => 10 }.with_indifferent_access
+ expected = { :c => 10 }.with_indifferent_access
+
+ [['a', 'b'], [:a, :b]].each do |keys|
+ # Should return a new hash without the given keys.
+ assert_equal expected, original.without(*keys), keys.inspect
+ assert_not_equal expected, original
+
+ # Should replace the hash without the given keys.
+ copy = original.dup
+ assert_equal expected, copy.without!(*keys)
+ assert_equal expected, copy
+ end
+ end
end
class IWriteMyOwnXML