Public utility methods for stringify/symbolize keys
This commit is contained in:
parent
12f031b013
commit
0e40e63ebc
|
@ -7,6 +7,7 @@
|
|||
* [#256](https://github.com/intridia/hashie/pull/256): Inherit key coercions - [@Erol](https://github.com/Erol).
|
||||
* [#259](https://github.com/intridia/hashie/pull/259): Fix handling of default proc values in Mash - [@Erol](https://github.com/Erol).
|
||||
* [#260](https://github.com/intridia/hashie/pull/260): Add block to Extensions::DeepMerge - [@galathius](https://github.com/galathius).
|
||||
* [#254](https://github.com/intridea/hashie/pull/254): Public utility methods for stringify/symbolize keys - [@maxlinc](https://github.com/maxlinc).
|
||||
* Your contribution here.
|
||||
|
||||
## 3.3.2 (11/26/2014)
|
||||
|
|
13
README.md
13
README.md
|
@ -141,6 +141,19 @@ end
|
|||
|
||||
The KeyConversion extension gives you the convenience methods of `symbolize_keys` and `stringify_keys` along with their bang counterparts. You can also include just stringify or just symbolize with `Hashie::Extensions::StringifyKeys` or `Hashie::Extensions::SymbolizeKeys`.
|
||||
|
||||
Hashie also has a utility method for converting keys on a Hash within including a mixin:
|
||||
|
||||
```ruby
|
||||
Hashie.symbolize_keys! hash
|
||||
# => Symbolizes keys of hash.
|
||||
Hashie.symbolize_keys hash
|
||||
# => Returns a copy of hash with keys symbolized.
|
||||
Hashie.stringify_keys hash
|
||||
# => Stringifies keys of hash.
|
||||
Hashie.stringify_keys hash
|
||||
# => Returns a copy of hash with keys stringified.
|
||||
```
|
||||
|
||||
### MergeInitializer
|
||||
|
||||
The MergeInitializer extension simply makes it possible to initialize a Hash subclass with another Hash, giving you a quick short-hand.
|
||||
|
|
|
@ -38,4 +38,9 @@ module Hashie
|
|||
autoload :SafeAssignment, 'hashie/extensions/mash/safe_assignment'
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
include Hashie::Extensions::StringifyKeys::ClassMethods
|
||||
include Hashie::Extensions::SymbolizeKeys::ClassMethods
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Hashie
|
|||
# test.stringify_keys!
|
||||
# test # => {'abc' => 'def'}
|
||||
def stringify_keys!
|
||||
_stringify_keys!(self)
|
||||
StringifyKeys.stringify_keys!(self)
|
||||
self
|
||||
end
|
||||
|
||||
|
@ -18,28 +18,50 @@ module Hashie
|
|||
dup.stringify_keys!
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Stringify all keys recursively within nested
|
||||
# hashes and arrays.
|
||||
def _stringify_keys_recursively!(object)
|
||||
case object
|
||||
when self.class
|
||||
object.stringify_keys!
|
||||
when ::Array
|
||||
object.each do |i|
|
||||
_stringify_keys_recursively!(i)
|
||||
module ClassMethods
|
||||
# Stringify all keys recursively within nested
|
||||
# hashes and arrays.
|
||||
# @api private
|
||||
def stringify_keys_recursively!(object)
|
||||
case object
|
||||
when self.class
|
||||
object.stringify_keys!
|
||||
when ::Array
|
||||
object.each do |i|
|
||||
stringify_keys_recursively!(i)
|
||||
end
|
||||
when ::Hash
|
||||
stringify_keys!(object)
|
||||
end
|
||||
end
|
||||
|
||||
# Convert all keys in the hash to strings.
|
||||
#
|
||||
# @param [::Hash] hash
|
||||
# @example
|
||||
# test = {:abc => 'def'}
|
||||
# test.stringify_keys!
|
||||
# test # => {'abc' => 'def'}
|
||||
def stringify_keys!(hash)
|
||||
hash.keys.each do |k|
|
||||
stringify_keys_recursively!(hash[k])
|
||||
hash[k.to_s] = hash.delete(k)
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
# Return a copy of hash with all keys converted
|
||||
# to strings.
|
||||
# @param [::Hash] hash
|
||||
def stringify_keys(hash)
|
||||
hash.dup.tap do | new_hash |
|
||||
stringify_keys! new_hash
|
||||
end
|
||||
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
|
||||
class << self
|
||||
include ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Hashie
|
|||
# test.symbolize_keys!
|
||||
# test # => {:abc => 'def'}
|
||||
def symbolize_keys!
|
||||
_symbolize_keys!(self)
|
||||
SymbolizeKeys.symbolize_keys!(self)
|
||||
self
|
||||
end
|
||||
|
||||
|
@ -18,28 +18,50 @@ module Hashie
|
|||
dup.symbolize_keys!
|
||||
end
|
||||
|
||||
protected
|
||||
module ClassMethods
|
||||
# Symbolize all keys recursively within nested
|
||||
# hashes and arrays.
|
||||
# @api private
|
||||
def symbolize_keys_recursively!(object)
|
||||
object.symbolize_keys! if object.respond_to? :symbolize_keys!
|
||||
|
||||
# Symbolize all keys recursively within nested
|
||||
# hashes and arrays.
|
||||
def _symbolize_keys_recursively!(object)
|
||||
case object
|
||||
when self.class
|
||||
object.symbolize_keys!
|
||||
when ::Array
|
||||
object.each do |i|
|
||||
_symbolize_keys_recursively!(i)
|
||||
case object
|
||||
when ::Array
|
||||
object.each do |i|
|
||||
symbolize_keys_recursively!(i)
|
||||
end
|
||||
when ::Hash
|
||||
symbolize_keys!(object)
|
||||
end
|
||||
end
|
||||
|
||||
# Convert all keys in hash to symbols.
|
||||
#
|
||||
# @param [Hash] hash
|
||||
# @example
|
||||
# test = {'abc' => 'def'}
|
||||
# Hashie.symbolize_keys! test
|
||||
# test # => {:abc => 'def'}
|
||||
def symbolize_keys!(hash)
|
||||
hash.keys.each do |k|
|
||||
symbolize_keys_recursively!(hash[k])
|
||||
hash[k.to_sym] = hash.delete(k)
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
# Return a copy of hash with all keys converted
|
||||
# to symbols.
|
||||
# @param [::Hash] hash
|
||||
def symbolize_keys(hash)
|
||||
hash.dup.tap do | new_hash |
|
||||
symbolize_keys! new_hash
|
||||
end
|
||||
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
|
||||
class << self
|
||||
include ClassMethods
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,58 +1,101 @@
|
|||
require 'spec_helper'
|
||||
require 'support/module_context'
|
||||
|
||||
def invoke(method)
|
||||
if subject == object
|
||||
subject.public_send(method)
|
||||
else
|
||||
subject.public_send(method, object)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'stringify_keys!' do
|
||||
it 'converts keys to strings' do
|
||||
object[:abc] = 'abc'
|
||||
object[123] = '123'
|
||||
invoke :stringify_keys!
|
||||
expect((object.keys & %w(abc 123)).size).to eq 2
|
||||
end
|
||||
|
||||
it 'converts nested instances of the same class' do
|
||||
object[:ab] = dummy_class.new
|
||||
object[:ab][:cd] = dummy_class.new
|
||||
object[:ab][:cd][:ef] = 'abcdef'
|
||||
invoke :stringify_keys!
|
||||
expect(object).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
|
||||
end
|
||||
|
||||
it 'converts nested hashes' do
|
||||
object[:ab] = { cd: { ef: 'abcdef' } }
|
||||
invoke :stringify_keys!
|
||||
expect(object).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
|
||||
end
|
||||
|
||||
it 'converts nested arrays' do
|
||||
object[:ab] = []
|
||||
object[:ab] << dummy_class.new
|
||||
object[:ab] << dummy_class.new
|
||||
object[:ab][0][:cd] = 'abcd'
|
||||
object[:ab][1][:ef] = 'abef'
|
||||
invoke :stringify_keys!
|
||||
expect(object).to eq('ab' => [{ 'cd' => 'abcd' }, { 'ef' => 'abef' }])
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'stringify_keys' do
|
||||
it 'converts keys to strings' do
|
||||
object[:abc] = 'def'
|
||||
copy = invoke :stringify_keys
|
||||
expect(copy['abc']).to eq 'def'
|
||||
end
|
||||
|
||||
it 'does not alter the original' do
|
||||
object[:abc] = 'def'
|
||||
copy = invoke :stringify_keys
|
||||
expect(object.keys).to eq [:abc]
|
||||
expect(copy.keys).to eq %w(abc)
|
||||
end
|
||||
end
|
||||
|
||||
describe Hashie::Extensions::StringifyKeys do
|
||||
include_context 'included hash module'
|
||||
let(:object) { subject }
|
||||
|
||||
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
|
||||
include_examples 'stringify_keys!'
|
||||
|
||||
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
|
||||
context 'class methods' do
|
||||
subject { described_class }
|
||||
let(:object) { Hash.new }
|
||||
|
||||
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)
|
||||
describe '.stringify_keys' do
|
||||
include_examples 'stringify_keys'
|
||||
end
|
||||
describe '.stringify_keys!' do
|
||||
include_examples 'stringify_keys!'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Hashie do
|
||||
let!(:dummy_class) do
|
||||
klass = Class.new(::Hash)
|
||||
klass.send :include, Hashie::Extensions::StringifyKeys
|
||||
klass
|
||||
end
|
||||
|
||||
subject { described_class }
|
||||
let(:object) { Hash.new }
|
||||
|
||||
describe '.stringify_keys' do
|
||||
include_examples 'stringify_keys'
|
||||
end
|
||||
describe '.stringify_keys!' do
|
||||
include_examples 'stringify_keys!'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,40 +1,69 @@
|
|||
require 'spec_helper'
|
||||
require 'support/module_context'
|
||||
|
||||
def invoke(method)
|
||||
if subject == object
|
||||
subject.public_send(method)
|
||||
else
|
||||
subject.public_send(method, object)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'symbolize_keys!' do
|
||||
it 'converts keys to symbols' do
|
||||
object['abc'] = 'abc'
|
||||
object['def'] = 'def'
|
||||
invoke :symbolize_keys!
|
||||
expect((object.keys & [:abc, :def]).size).to eq 2
|
||||
end
|
||||
|
||||
it 'converts nested instances of the same class' do
|
||||
object['ab'] = dummy_class.new
|
||||
object['ab']['cd'] = dummy_class.new
|
||||
object['ab']['cd']['ef'] = 'abcdef'
|
||||
invoke :symbolize_keys!
|
||||
expect(object).to eq(ab: { cd: { ef: 'abcdef' } })
|
||||
end
|
||||
|
||||
it 'converts nested hashes' do
|
||||
object['ab'] = { 'cd' => { 'ef' => 'abcdef' } }
|
||||
invoke :symbolize_keys!
|
||||
expect(object).to eq(ab: { cd: { ef: 'abcdef' } })
|
||||
end
|
||||
|
||||
it 'performs deep conversion within nested arrays' do
|
||||
object['ab'] = []
|
||||
object['ab'] << dummy_class.new
|
||||
object['ab'] << dummy_class.new
|
||||
object['ab'][0]['cd'] = 'abcd'
|
||||
object['ab'][1]['ef'] = 'abef'
|
||||
new_object = invoke :symbolize_keys
|
||||
expect(new_object).to eq(ab: [{ cd: 'abcd' }, { ef: 'abef' }])
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'symbolize_keys' do
|
||||
it 'converts keys to symbols' do
|
||||
object['abc'] = 'def'
|
||||
copy = invoke :symbolize_keys
|
||||
expect(copy[:abc]).to eq 'def'
|
||||
end
|
||||
|
||||
it 'does not alter the original' do
|
||||
object['abc'] = 'def'
|
||||
copy = invoke :symbolize_keys
|
||||
expect(object.keys).to eq ['abc']
|
||||
expect(copy.keys).to eq [:abc]
|
||||
end
|
||||
end
|
||||
|
||||
describe Hashie::Extensions::SymbolizeKeys do
|
||||
include_context 'included hash module'
|
||||
let(:object) { subject }
|
||||
|
||||
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
|
||||
include_examples 'symbolize_keys!'
|
||||
let(:object) { subject }
|
||||
|
||||
it 'returns itself' do
|
||||
expect(subject.symbolize_keys!).to eq subject
|
||||
|
@ -42,17 +71,36 @@ describe Hashie::Extensions::SymbolizeKeys do
|
|||
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
|
||||
include_examples 'symbolize_keys'
|
||||
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]
|
||||
context 'class methods' do
|
||||
subject { described_class }
|
||||
let(:object) { Hash.new }
|
||||
|
||||
describe '.symbolize_keys' do
|
||||
include_examples 'symbolize_keys'
|
||||
end
|
||||
describe '.symbolize_keys!' do
|
||||
include_examples 'symbolize_keys!'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Hashie do
|
||||
let!(:dummy_class) do
|
||||
klass = Class.new(::Hash)
|
||||
klass.send :include, Hashie::Extensions::StringifyKeys
|
||||
klass
|
||||
end
|
||||
|
||||
subject { described_class }
|
||||
let(:object) { Hash.new }
|
||||
|
||||
describe '.symbolize_keys' do
|
||||
include_examples 'symbolize_keys'
|
||||
end
|
||||
describe '.symbolize_keys!' do
|
||||
include_examples 'symbolize_keys!'
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue