Update key conversion extensions

Fixing collision with ActiveSupport

ActiveSupport implementation is not recursive
This commit is contained in:
Bartosz Kopiński 2014-11-30 05:27:58 +01:00 committed by dB
parent 60b8e803d0
commit ea2076ba6c
7 changed files with 164 additions and 129 deletions

View File

@ -1,5 +1,6 @@
## Next
* [#247](https://github.com/intridea/hashie/pull/247): Fixed #stringify_keys and #symbolize_keys collision with ActiveSupport - [@bartoszkopinski](https://github.com/bartoszkopinski).
* Your contribution here.
## 3.3.2 (11/26/2014)

View File

@ -8,10 +8,7 @@ module Hashie
# test.stringify_keys!
# test # => {'abc' => 'def'}
def stringify_keys!
keys.each do |k|
stringify_keys_recursively!(self[k])
self[k.to_s] = delete(k)
end
_stringify_keys!(self)
self
end
@ -25,24 +22,23 @@ module Hashie
# Stringify all keys recursively within nested
# hashes and arrays.
def stringify_keys_recursively!(object)
if self.class === object
def _stringify_keys_recursively!(object)
case object
when self.class
object.stringify_keys!
elsif ::Array === object
when ::Array
object.each do |i|
stringify_keys_recursively!(i)
_stringify_keys_recursively!(i)
end
object
elsif object.respond_to?(:stringify_keys!)
object.stringify_keys!
elsif ::Hash === object
object.keys.each do |k|
stringify_keys_recursively!(object[k])
object[k.to_s] = object.delete(k)
end
object
else
object
when ::Hash
_stringify_keys!(object)
end
end
def _stringify_keys!(hash)
hash.keys.each do |k|
_stringify_keys_recursively!(hash[k])
hash[k.to_s] = hash.delete(k)
end
end
end

View File

@ -8,10 +8,7 @@ module Hashie
# test.symbolize_keys!
# test # => {:abc => 'def'}
def symbolize_keys!
keys.each do |k|
symbolize_keys_recursively!(self[k])
self[k.to_sym] = delete(k)
end
_symbolize_keys!(self)
self
end
@ -25,18 +22,23 @@ module Hashie
# Symbolize all keys recursively within nested
# hashes and arrays.
def symbolize_keys_recursively!(object)
if self.class === object
def _symbolize_keys_recursively!(object)
case object
when self.class
object.symbolize_keys!
elsif ::Array === object
when ::Array
object.each do |i|
symbolize_keys_recursively!(i)
_symbolize_keys_recursively!(i)
end
object
elsif object.respond_to?(:symbolize_keys!)
object.symbolize_keys!
else
object
when ::Hash
_symbolize_keys!(object)
end
end
def _symbolize_keys!(hash)
hash.keys.each do |k|
_symbolize_keys_recursively!(hash[k])
hash[k.to_sym] = hash.delete(k)
end
end
end

View File

@ -1,103 +1,12 @@
require 'spec_helper'
require 'support/module_context'
describe Hashie::Extensions::KeyConversion do
subject do
klass = Class.new(::Hash)
klass.send :include, Hashie::Extensions::KeyConversion
klass
end
include_context 'included hash module'
let(:instance) { subject.new }
it { should respond_to(:stringify_keys) }
it { should respond_to(:stringify_keys!) }
describe '#stringify_keys!' do
it 'converts keys to strings' do
instance[:abc] = 'abc'
instance[123] = '123'
instance.stringify_keys!
expect((instance.keys & %w(abc 123)).size).to eq 2
end
it 'performs deep conversion within nested hashes' do
instance[:ab] = subject.new
instance[:ab][:cd] = subject.new
instance[:ab][:cd][:ef] = 'abcdef'
instance.stringify_keys!
expect(instance).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
end
it 'performs deep conversion within nested arrays' do
instance[:ab] = []
instance[:ab] << subject.new
instance[:ab] << subject.new
instance[:ab][0][:cd] = 'abcd'
instance[:ab][1][:ef] = 'abef'
instance.stringify_keys!
expect(instance).to eq('ab' => [{ 'cd' => 'abcd' }, { 'ef' => 'abef' }])
end
it 'returns itself' do
expect(instance.stringify_keys!).to eq instance
end
end
describe '#stringify_keys' do
it 'converts keys to strings' do
instance[:abc] = 'def'
copy = instance.stringify_keys
expect(copy['abc']).to eq 'def'
end
it 'does not alter the original' do
instance[:abc] = 'def'
copy = instance.stringify_keys
expect(instance.keys).to eq [:abc]
expect(copy.keys).to eq %w(abc)
end
end
describe '#symbolize_keys!' do
it 'converts keys to symbols' do
instance['abc'] = 'abc'
instance['def'] = 'def'
instance.symbolize_keys!
expect((instance.keys & [:abc, :def]).size).to eq 2
end
it 'performs deep conversion within nested hashes' do
instance['ab'] = subject.new
instance['ab']['cd'] = subject.new
instance['ab']['cd']['ef'] = 'abcdef'
instance.symbolize_keys!
expect(instance).to eq(ab: { cd: { ef: 'abcdef' } })
end
it 'performs deep conversion within nested arrays' do
instance['ab'] = []
instance['ab'] << subject.new
instance['ab'] << subject.new
instance['ab'][0]['cd'] = 'abcd'
instance['ab'][1]['ef'] = 'abef'
instance.symbolize_keys!
expect(instance).to eq(ab: [{ cd: 'abcd' }, { ef: 'abef' }])
end
it 'returns itself' do
expect(instance.symbolize_keys!).to eq instance
end
end
describe '#symbolize_keys' do
it 'converts keys to symbols' do
instance['abc'] = 'def'
copy = instance.symbolize_keys
expect(copy[:abc]).to eq 'def'
end
it 'does not alter the original' do
instance['abc'] = 'def'
copy = instance.symbolize_keys
expect(instance.keys).to eq ['abc']
expect(copy.keys).to eq [:abc]
end
end
it { should respond_to(:symbolize_keys) }
it { should respond_to(:symbolize_keys!) }
end

View File

@ -0,0 +1,58 @@
require 'spec_helper'
require 'support/module_context'
describe Hashie::Extensions::StringifyKeys do
include_context 'included hash module'
describe '#stringify_keys!' do
it 'converts keys to strings' do
subject[:abc] = 'abc'
subject[123] = '123'
subject.stringify_keys!
expect((subject.keys & %w(abc 123)).size).to eq 2
end
it 'converts nested instances of the same class' do
subject[:ab] = dummy_class.new
subject[:ab][:cd] = dummy_class.new
subject[:ab][:cd][:ef] = 'abcdef'
subject.stringify_keys!
expect(subject).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
end
it 'converts nested hashes' do
subject[:ab] = { cd: { ef: 'abcdef' } }
subject.stringify_keys!
expect(subject).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
end
it 'converts nested arrays' do
subject[:ab] = []
subject[:ab] << dummy_class.new
subject[:ab] << dummy_class.new
subject[:ab][0][:cd] = 'abcd'
subject[:ab][1][:ef] = 'abef'
subject.stringify_keys!
expect(subject).to eq('ab' => [{ 'cd' => 'abcd' }, { 'ef' => 'abef' }])
end
it 'returns itself' do
expect(subject.stringify_keys!).to eq subject
end
end
describe '#stringify_keys' do
it 'converts keys to strings' do
subject[:abc] = 'def'
copy = subject.stringify_keys
expect(copy['abc']).to eq 'def'
end
it 'does not alter the original' do
subject[:abc] = 'def'
copy = subject.stringify_keys
expect(subject.keys).to eq [:abc]
expect(copy.keys).to eq %w(abc)
end
end
end

View File

@ -0,0 +1,58 @@
require 'spec_helper'
require 'support/module_context'
describe Hashie::Extensions::SymbolizeKeys do
include_context 'included hash module'
describe '#symbolize_keys!' do
it 'converts keys to symbols' do
subject['abc'] = 'abc'
subject['def'] = 'def'
subject.symbolize_keys!
expect((subject.keys & [:abc, :def]).size).to eq 2
end
it 'converts nested instances of the same class' do
subject['ab'] = dummy_class.new
subject['ab']['cd'] = dummy_class.new
subject['ab']['cd']['ef'] = 'abcdef'
subject.symbolize_keys!
expect(subject).to eq(ab: { cd: { ef: 'abcdef' } })
end
it 'converts nested hashes' do
subject['ab'] = { 'cd' => { 'ef' => 'abcdef' } }
subject.symbolize_keys!
expect(subject).to eq(ab: { cd: { ef: 'abcdef' } })
end
it 'performs deep conversion within nested arrays' do
subject['ab'] = []
subject['ab'] << dummy_class.new
subject['ab'] << dummy_class.new
subject['ab'][0]['cd'] = 'abcd'
subject['ab'][1]['ef'] = 'abef'
subject.symbolize_keys!
expect(subject).to eq(ab: [{ cd: 'abcd' }, { ef: 'abef' }])
end
it 'returns itself' do
expect(subject.symbolize_keys!).to eq subject
end
end
describe '#symbolize_keys' do
it 'converts keys to symbols' do
subject['abc'] = 'def'
copy = subject.symbolize_keys
expect(copy[:abc]).to eq 'def'
end
it 'does not alter the original' do
subject['abc'] = 'def'
copy = subject.symbolize_keys
expect(subject.keys).to eq ['abc']
expect(copy.keys).to eq [:abc]
end
end
end

View File

@ -0,0 +1,11 @@
shared_context 'included hash module' do
let!(:dummy_class) do
klass = Class.new(::Hash)
klass.send :include, described_class
klass
end
subject do
dummy_class.new
end
end