diff options
author | Vincent Esche <vincent.esche@namics.com> | 2015-06-05 18:48:09 +0200 |
---|---|---|
committer | Vincent Esche <regexident@gmail.com> | 2015-06-08 02:01:54 +0200 |
commit | 489309af7ffd8b4fe02bd839924b319cba8aa318 (patch) | |
tree | 56a2667e2deef61ba389c9a1a8b219fe44bb65ee | |
parent | b7405dca6d8d03c1650083119215a6eaf4125d91 (diff) | |
download | hashie-489309af7ffd8b4fe02bd839924b319cba8aa318.tar.gz |
Fix bug (#303) preventing use of deep_merge/stringify_keys/symbolize_keys on extended singleton objects.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | lib/hashie/extensions/deep_merge.rb | 4 | ||||
-rw-r--r-- | lib/hashie/extensions/stringify_keys.rb | 11 | ||||
-rw-r--r-- | lib/hashie/extensions/symbolize_keys.rb | 13 | ||||
-rw-r--r-- | spec/hashie/extensions/deep_merge_spec.rb | 20 | ||||
-rw-r--r-- | spec/hashie/extensions/stringify_keys_spec.rb | 23 | ||||
-rw-r--r-- | spec/hashie/extensions/symbolize_keys_spec.rb | 23 |
7 files changed, 85 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a5740cf..81d2289 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Next Release * Your contribution here. +* [#304](https://github.com/intridea/hashie/pull/304): Ensured compatibility of `Hash` extensions with singleton objects - [@regexident](https://github.com/regexident). ## 3.4.2 (6/2/2015) diff --git a/lib/hashie/extensions/deep_merge.rb b/lib/hashie/extensions/deep_merge.rb index d7222a3..df0887d 100644 --- a/lib/hashie/extensions/deep_merge.rb +++ b/lib/hashie/extensions/deep_merge.rb @@ -3,7 +3,9 @@ module Hashie module DeepMerge # Returns a new hash with +self+ and +other_hash+ merged recursively. def deep_merge(other_hash, &block) - dup.deep_merge!(other_hash, &block) + copy = dup + copy.extend(Hashie::Extensions::DeepMerge) unless copy.respond_to?(:deep_merge!) + copy.deep_merge!(other_hash, &block) end # Returns a new hash with +self+ and +other_hash+ merged recursively. diff --git a/lib/hashie/extensions/stringify_keys.rb b/lib/hashie/extensions/stringify_keys.rb index 13d50bc..41b0fe3 100644 --- a/lib/hashie/extensions/stringify_keys.rb +++ b/lib/hashie/extensions/stringify_keys.rb @@ -15,7 +15,7 @@ module Hashie # Return a new hash with all keys converted # to strings. def stringify_keys - dup.stringify_keys! + StringifyKeys.stringify_keys(self) end module ClassMethods @@ -25,7 +25,7 @@ module Hashie def stringify_keys_recursively!(object) case object when self.class - object.stringify_keys! + stringify_keys!(object) when ::Array object.each do |i| stringify_keys_recursively!(i) @@ -43,6 +43,7 @@ module Hashie # test.stringify_keys! # test # => {'abc' => 'def'} def stringify_keys!(hash) + hash.extend(Hashie::Extensions::StringifyKeys) unless hash.respond_to?(:stringify_keys!) hash.keys.each do |k| stringify_keys_recursively!(hash[k]) hash[k.to_s] = hash.delete(k) @@ -54,8 +55,10 @@ module Hashie # to strings. # @param [::Hash] hash def stringify_keys(hash) - hash.dup.tap do | new_hash | - stringify_keys! new_hash + copy = hash.dup + copy.extend(Hashie::Extensions::StringifyKeys) unless copy.respond_to?(:stringify_keys!) + copy.tap do |new_hash| + stringify_keys!(new_hash) end end end diff --git a/lib/hashie/extensions/symbolize_keys.rb b/lib/hashie/extensions/symbolize_keys.rb index 12d0669..274889c 100644 --- a/lib/hashie/extensions/symbolize_keys.rb +++ b/lib/hashie/extensions/symbolize_keys.rb @@ -15,7 +15,7 @@ module Hashie # Return a new hash with all keys converted # to symbols. def symbolize_keys - dup.symbolize_keys! + SymbolizeKeys.symbolize_keys(self) end module ClassMethods @@ -23,9 +23,9 @@ module Hashie # hashes and arrays. # @api private def symbolize_keys_recursively!(object) - object.symbolize_keys! if object.respond_to? :symbolize_keys! - case object + when self.class + symbolize_keys!(object) when ::Array object.each do |i| symbolize_keys_recursively!(i) @@ -43,6 +43,7 @@ module Hashie # Hashie.symbolize_keys! test # test # => {:abc => 'def'} def symbolize_keys!(hash) + hash.extend(Hashie::Extensions::SymbolizeKeys) unless hash.respond_to?(:symbolize_keys!) hash.keys.each do |k| symbolize_keys_recursively!(hash[k]) hash[k.to_sym] = hash.delete(k) @@ -54,8 +55,10 @@ module Hashie # to symbols. # @param [::Hash] hash def symbolize_keys(hash) - hash.dup.tap do | new_hash | - symbolize_keys! new_hash + copy = hash.dup + copy.extend(Hashie::Extensions::SymbolizeKeys) unless copy.respond_to?(:symbolize_keys!) + copy.tap do |new_hash| + symbolize_keys!(new_hash) end end end diff --git a/spec/hashie/extensions/deep_merge_spec.rb b/spec/hashie/extensions/deep_merge_spec.rb index cd68523..0815c15 100644 --- a/spec/hashie/extensions/deep_merge_spec.rb +++ b/spec/hashie/extensions/deep_merge_spec.rb @@ -42,4 +42,24 @@ describe Hashie::Extensions::DeepMerge do expect(h1).to eq expected_hash end end + + context 'from extended object' do + subject { Hash } + let(:h1) { subject.new.merge(a: 100, c: { c1: 100 }).extend(Hashie::Extensions::DeepMerge) } + let(:h2) { { b: 250, c: { c1: 200 } } } + let(:expected_hash) { { a: 100, b: 250, c: { c1: 200 } } } + + it 'does not raise error' do + expect { h1.deep_merge(h2) } .not_to raise_error + end + + it 'deep merges two hashes' do + expect(h1.deep_merge(h2)).to eq expected_hash + end + + it 'deep merges another hash in place via bang method' do + h1.deep_merge!(h2) + expect(h1).to eq expected_hash + end + end end diff --git a/spec/hashie/extensions/stringify_keys_spec.rb b/spec/hashie/extensions/stringify_keys_spec.rb index b0f8aa6..f5f78d8 100644 --- a/spec/hashie/extensions/stringify_keys_spec.rb +++ b/spec/hashie/extensions/stringify_keys_spec.rb @@ -80,6 +80,29 @@ describe Hashie::Extensions::StringifyKeys do include_examples 'stringify_keys!' end end + + context 'singleton methods' do + subject { Hash } + let(:object) { subject.new.merge(a: 1, b: { c: 2 }).extend(Hashie::Extensions::StringifyKeys) } + let(:expected_hash) { { 'a' => 1, 'b' => { 'c' => 2 } } } + + describe '.stringify_keys' do + it 'does not raise error' do + expect { object.stringify_keys } .not_to raise_error + end + it 'produces expected stringified hash' do + expect(object.stringify_keys).to eq(expected_hash) + end + end + describe '.stringify_keys!' do + it 'does not raise error' do + expect { object.stringify_keys! } .not_to raise_error + end + it 'produces expected stringified hash' do + expect(object.stringify_keys!).to eq(expected_hash) + end + end + end end describe Hashie do diff --git a/spec/hashie/extensions/symbolize_keys_spec.rb b/spec/hashie/extensions/symbolize_keys_spec.rb index 862117b..b62fbe4 100644 --- a/spec/hashie/extensions/symbolize_keys_spec.rb +++ b/spec/hashie/extensions/symbolize_keys_spec.rb @@ -85,6 +85,29 @@ describe Hashie::Extensions::SymbolizeKeys do include_examples 'symbolize_keys!' end end + + context 'singleton methods' do + subject { Hash } + let(:object) { subject.new.merge('a' => 1, 'b' => { 'c' => 2 }).extend(Hashie::Extensions::SymbolizeKeys) } + let(:expected_hash) { { a: 1, b: { c: 2 } } } + + describe '.symbolize_keys' do + it 'does not raise error' do + expect { object.symbolize_keys }.not_to raise_error + end + it 'produces expected symbolized hash' do + expect(object.symbolize_keys).to eq(expected_hash) + end + end + describe '.symbolize_keys!' do + it 'does not raise error' do + expect { object.symbolize_keys! }.not_to raise_error + end + it 'produces expected symbolized hash' do + expect(object.symbolize_keys!).to eq(expected_hash) + end + end + end end describe Hashie do |