Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add Hash#deep_remove and #deep_remove! methods

  • Loading branch information...
commit f2ad961ff4972119fce8b61639492e4710dfe906 1 parent 1402376
@alexeymuranov authored
View
1  activesupport/lib/active_support/core_ext/hash.rb
@@ -2,6 +2,7 @@
require 'active_support/core_ext/hash/deep_dup'
require 'active_support/core_ext/hash/deep_filter'
require 'active_support/core_ext/hash/deep_merge'
+require 'active_support/core_ext/hash/deep_remove'
require 'active_support/core_ext/hash/diff'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/indifferent_access'
View
35 activesupport/lib/active_support/core_ext/hash/deep_remove.rb
@@ -0,0 +1,35 @@
+class Hash
+ # Returns a new hash with keys and nested keys indicated by +key_hash+ removed.
+ # Example:
+ #
+ # h = { :a => 1, :b => { :c => 2, :d => 3 }, :e => 4 }
+ # kh = { :a => true, :b => { :c => true } }
+ # h.deep_remove(kh)
+ # # => { :b => { :d => 3}, :e => 4 }
+ def deep_remove(key_hash)
+ new_hash = self.class.new
+ each_pair do |k,v|
+ unless key_hash.has_key?(k) && ov = key_hash[k]
+ new_hash[k] = v.is_a?(Hash) ? v.deep_dup : v
+ else
+ new_hash[k] = v.deep_remove(ov) if ov.is_a?(Hash)
+ end
+ end
+ new_hash
+ end
+
+ # Returns a new hash with keys and nested keys indicated by +key_hash+ removed.
+ # Modifies the receiver in place.
+ def deep_remove!(key_hash)
+ key_hash.each_pair do |k,ov|
+ if ov
+ if ov.is_a?(Hash)
+ self[k].deep_remove!(ov)
+ else
+ delete(k)
+ end
+ end
+ end
+ self
+ end
+end
View
24 activesupport/test/core_ext/hash_ext_test.rb
@@ -402,6 +402,30 @@ def test_deep_filter_on_indifferent_access
assert_equal expected, hash_1
end
+ def test_deep_remove
+ hash_1 = { :a => 1, :b => { :c => 2, :d => 3 }, :e => 4 }
+ kh = { :a => true, :b => { :c => true } }
+ hash_2 = hash_1.deep_remove(kh)
+ expected = { :b => { :d => 3}, :e => 4 }
+ assert_equal expected, hash_2
+ hash_2[:b][:d] = 0
+ assert_equal 3, hash_1[:b][:d]
+ assert_equal expected, hash_1.deep_remove!(kh)
+ assert_equal expected, hash_1
+ end
+
+ def test_deep_remove_on_indifferent_access
+ hash_1 = HashWithIndifferentAccess.new({ :a => 1, :b => HashWithIndifferentAccess.new({ :c => 2, :d => 3 }), :e => 4 })
+ kh = HashWithIndifferentAccess.new({ :a => true, :b => HashWithIndifferentAccess.new({ :c => true }) })
+ hash_2 = hash_1.deep_remove(kh)
+ expected = { 'b' => { 'd' => 3}, 'e' => 4 }
+ assert_equal expected, hash_2
+ hash_2[:b][:d] = 0
+ assert_equal 3, hash_1[:b][:d]
+ assert_equal expected, hash_1.deep_remove!(kh)
+ assert_equal expected, hash_1
+ end
+
def test_store_on_indifferent_access
hash = HashWithIndifferentAccess.new
hash.store(:test1, 1)
Please sign in to comment.
Something went wrong with that request. Please try again.