hashie 2.1.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +524 -59
- data/CONTRIBUTING.md +24 -7
- data/README.md +781 -90
- data/Rakefile +19 -2
- data/UPGRADING.md +245 -0
- data/hashie.gemspec +21 -13
- data/lib/hashie.rb +60 -21
- data/lib/hashie/array.rb +21 -0
- data/lib/hashie/clash.rb +24 -12
- data/lib/hashie/dash.rb +96 -33
- data/lib/hashie/extensions/active_support/core_ext/hash.rb +14 -0
- data/lib/hashie/extensions/array/pretty_inspect.rb +19 -0
- data/lib/hashie/extensions/coercion.rb +124 -18
- data/lib/hashie/extensions/dash/coercion.rb +25 -0
- data/lib/hashie/extensions/dash/indifferent_access.rb +56 -0
- data/lib/hashie/extensions/dash/property_translation.rb +191 -0
- data/lib/hashie/extensions/deep_fetch.rb +7 -5
- data/lib/hashie/extensions/deep_find.rb +69 -0
- data/lib/hashie/extensions/deep_locate.rb +113 -0
- data/lib/hashie/extensions/deep_merge.rb +35 -12
- data/lib/hashie/extensions/ignore_undeclared.rb +11 -5
- data/lib/hashie/extensions/indifferent_access.rb +28 -16
- data/lib/hashie/extensions/key_conflict_warning.rb +55 -0
- data/lib/hashie/extensions/key_conversion.rb +0 -82
- data/lib/hashie/extensions/mash/define_accessors.rb +90 -0
- data/lib/hashie/extensions/mash/keep_original_keys.rb +53 -0
- data/lib/hashie/extensions/mash/permissive_respond_to.rb +61 -0
- data/lib/hashie/extensions/mash/safe_assignment.rb +18 -0
- data/lib/hashie/extensions/mash/symbolize_keys.rb +38 -0
- data/lib/hashie/extensions/method_access.rb +154 -11
- data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +48 -0
- data/lib/hashie/extensions/pretty_inspect.rb +19 -0
- data/lib/hashie/extensions/ruby_version.rb +60 -0
- data/lib/hashie/extensions/ruby_version_check.rb +21 -0
- data/lib/hashie/extensions/strict_key_access.rb +77 -0
- data/lib/hashie/extensions/stringify_keys.rb +71 -0
- data/lib/hashie/extensions/symbolize_keys.rb +71 -0
- data/lib/hashie/hash.rb +27 -8
- data/lib/hashie/logger.rb +18 -0
- data/lib/hashie/mash.rb +235 -57
- data/lib/hashie/railtie.rb +21 -0
- data/lib/hashie/rash.rb +40 -16
- data/lib/hashie/trash.rb +2 -88
- data/lib/hashie/utils.rb +44 -0
- data/lib/hashie/version.rb +1 -1
- metadata +42 -81
- data/.gitignore +0 -9
- data/.rspec +0 -2
- data/.rubocop.yml +0 -36
- data/.travis.yml +0 -15
- data/Gemfile +0 -11
- data/Guardfile +0 -5
- data/lib/hashie/hash_extensions.rb +0 -47
- data/spec/hashie/clash_spec.rb +0 -48
- data/spec/hashie/dash_spec.rb +0 -338
- data/spec/hashie/extensions/coercion_spec.rb +0 -156
- data/spec/hashie/extensions/deep_fetch_spec.rb +0 -70
- data/spec/hashie/extensions/deep_merge_spec.rb +0 -22
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +0 -23
- data/spec/hashie/extensions/indifferent_access_spec.rb +0 -152
- data/spec/hashie/extensions/key_conversion_spec.rb +0 -103
- data/spec/hashie/extensions/merge_initializer_spec.rb +0 -23
- data/spec/hashie/extensions/method_access_spec.rb +0 -121
- data/spec/hashie/hash_spec.rb +0 -66
- data/spec/hashie/mash_spec.rb +0 -467
- data/spec/hashie/rash_spec.rb +0 -44
- data/spec/hashie/trash_spec.rb +0 -193
- data/spec/hashie/version_spec.rb +0 -7
- data/spec/spec.opts +0 -3
- data/spec/spec_helper.rb +0 -8
@@ -1,156 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::Coercion do
|
4
|
-
class Initializable
|
5
|
-
attr_reader :coerced, :value
|
6
|
-
|
7
|
-
def initialize(obj, coerced = false)
|
8
|
-
@coerced = coerced
|
9
|
-
@value = obj.class.to_s
|
10
|
-
end
|
11
|
-
|
12
|
-
def coerced?
|
13
|
-
!!@coerced
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Coercable < Initializable
|
18
|
-
def self.coerce(obj)
|
19
|
-
new(obj, true)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
before(:each) do
|
24
|
-
class ExampleCoercableHash < Hash
|
25
|
-
include Hashie::Extensions::Coercion
|
26
|
-
include Hashie::Extensions::MergeInitializer
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
subject { ExampleCoercableHash }
|
31
|
-
|
32
|
-
let(:instance) { subject.new }
|
33
|
-
|
34
|
-
describe '#coerce_key' do
|
35
|
-
it { expect(subject).to be_respond_to(:coerce_key) }
|
36
|
-
|
37
|
-
it 'runs through coerce on a specified key' do
|
38
|
-
subject.coerce_key :foo, Coercable
|
39
|
-
|
40
|
-
instance[:foo] = 'bar'
|
41
|
-
expect(instance[:foo]).to be_coerced
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'supports an array of keys' do
|
45
|
-
subject.coerce_keys :foo, :bar, Coercable
|
46
|
-
|
47
|
-
instance[:foo] = 'bar'
|
48
|
-
instance[:bar] = 'bax'
|
49
|
-
expect(instance[:foo]).to be_coerced
|
50
|
-
expect(instance[:bar]).to be_coerced
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'calls #new if no coerce method is available' do
|
54
|
-
subject.coerce_key :foo, Initializable
|
55
|
-
|
56
|
-
instance[:foo] = 'bar'
|
57
|
-
expect(instance[:foo].value).to eq 'String'
|
58
|
-
expect(instance[:foo]).not_to be_coerced
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'coerces when the merge initializer is used' do
|
62
|
-
subject.coerce_key :foo, Coercable
|
63
|
-
instance = subject.new(foo: 'bar')
|
64
|
-
|
65
|
-
expect(instance[:foo]).to be_coerced
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'when #replace is used' do
|
69
|
-
before { subject.coerce_key :foo, :bar, Coercable }
|
70
|
-
|
71
|
-
let(:instance) do
|
72
|
-
subject.new(foo: 'bar').replace(foo: 'foz', bar: 'baz', hi: 'bye')
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'coerces relevant keys' do
|
76
|
-
expect(instance[:foo]).to be_coerced
|
77
|
-
expect(instance[:bar]).to be_coerced
|
78
|
-
expect(instance[:hi]).not_to respond_to(:coerced?)
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'sets correct values' do
|
82
|
-
expect(instance[:hi]).to eq 'bye'
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'when used with a Mash' do
|
87
|
-
class UserMash < Hashie::Mash
|
88
|
-
end
|
89
|
-
class TweetMash < Hashie::Mash
|
90
|
-
include Hashie::Extensions::Coercion
|
91
|
-
coerce_key :user, UserMash
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'coerces with instance initialization' do
|
95
|
-
tweet = TweetMash.new(user: { email: 'foo@bar.com' })
|
96
|
-
expect(tweet[:user]).to be_a(UserMash)
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'coerces when setting with attribute style' do
|
100
|
-
tweet = TweetMash.new
|
101
|
-
tweet.user = { email: 'foo@bar.com' }
|
102
|
-
expect(tweet[:user]).to be_a(UserMash)
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'coerces when setting with string index' do
|
106
|
-
tweet = TweetMash.new
|
107
|
-
tweet['user'] = { email: 'foo@bar.com' }
|
108
|
-
expect(tweet[:user]).to be_a(UserMash)
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'coerces when setting with symbol index' do
|
112
|
-
tweet = TweetMash.new
|
113
|
-
tweet[:user] = { email: 'foo@bar.com' }
|
114
|
-
expect(tweet[:user]).to be_a(UserMash)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe '#coerce_value' do
|
120
|
-
context 'with strict: true' do
|
121
|
-
it 'coerces any value of the exact right class' do
|
122
|
-
subject.coerce_value String, Coercable
|
123
|
-
|
124
|
-
instance[:foo] = 'bar'
|
125
|
-
instance[:bar] = 'bax'
|
126
|
-
instance[:hi] = :bye
|
127
|
-
expect(instance[:foo]).to be_coerced
|
128
|
-
expect(instance[:bar]).to be_coerced
|
129
|
-
expect(instance[:hi]).not_to respond_to(:coerced?)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'coerces values from a #replace call' do
|
133
|
-
subject.coerce_value String, Coercable
|
134
|
-
|
135
|
-
instance[:foo] = :bar
|
136
|
-
instance.replace(foo: 'bar', bar: 'bax')
|
137
|
-
expect(instance[:foo]).to be_coerced
|
138
|
-
expect(instance[:bar]).to be_coerced
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'does not coerce superclasses' do
|
142
|
-
klass = Class.new(String)
|
143
|
-
subject.coerce_value klass, Coercable
|
144
|
-
|
145
|
-
instance[:foo] = 'bar'
|
146
|
-
expect(instance[:foo]).not_to be_kind_of(Coercable)
|
147
|
-
instance[:foo] = klass.new
|
148
|
-
expect(instance[:foo]).to be_kind_of(Coercable)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
after(:each) do
|
154
|
-
Object.send(:remove_const, :ExampleCoercableHash)
|
155
|
-
end
|
156
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Hashie
|
4
|
-
module Extensions
|
5
|
-
describe DeepFetch do
|
6
|
-
subject { Class.new(Hash) { include Hashie::Extensions::DeepFetch } }
|
7
|
-
let(:hash) do
|
8
|
-
{
|
9
|
-
library: {
|
10
|
-
books: [
|
11
|
-
{ title: 'Call of the Wild' },
|
12
|
-
{ title: 'Moby Dick' }
|
13
|
-
],
|
14
|
-
location: {
|
15
|
-
address: '123 Library St.'
|
16
|
-
}
|
17
|
-
}
|
18
|
-
}
|
19
|
-
end
|
20
|
-
let(:instance) { subject.new.update(hash) }
|
21
|
-
|
22
|
-
describe '#deep_fetch' do
|
23
|
-
it 'extracts a value from a nested hash' do
|
24
|
-
expect(instance.deep_fetch(:library, :location, :address)).to eq('123 Library St.')
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'extracts a value from a nested array' do
|
28
|
-
expect(instance.deep_fetch(:library, :books, 1, :title)).to eq('Moby Dick')
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'when one of the keys is not present' do
|
32
|
-
context 'when a block is provided' do
|
33
|
-
it 'returns the value of the block' do
|
34
|
-
value = instance.deep_fetch(:library, :unknown_key, :location) { 'block value' }
|
35
|
-
expect(value).to eq('block value')
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context 'when a block is not provided' do
|
40
|
-
context 'when the nested object is an array' do
|
41
|
-
it 'raises an UndefinedPathError' do
|
42
|
-
expect do
|
43
|
-
instance.deep_fetch(:library, :books, 2)
|
44
|
-
end.to(
|
45
|
-
raise_error(
|
46
|
-
DeepFetch::UndefinedPathError,
|
47
|
-
'Could not fetch path (library > books > 2) at 2'
|
48
|
-
)
|
49
|
-
)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'when the nested object is a hash' do
|
54
|
-
it 'raises a UndefinedPathError' do
|
55
|
-
expect do
|
56
|
-
instance.deep_fetch(:library, :location, :unknown_key)
|
57
|
-
end.to(
|
58
|
-
raise_error(
|
59
|
-
DeepFetch::UndefinedPathError,
|
60
|
-
'Could not fetch path (library > location > unknown_key) at unknown_key'
|
61
|
-
)
|
62
|
-
)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::DeepMerge do
|
4
|
-
class DeepMergeHash < Hash
|
5
|
-
include Hashie::Extensions::DeepMerge
|
6
|
-
end
|
7
|
-
|
8
|
-
subject { DeepMergeHash }
|
9
|
-
|
10
|
-
let(:h1) { subject.new.merge(a: 'a', a1: 42, b: 'b', c: { c1: 'c1', c2: { a: 'b' }, c3: { d1: 'd1' } }) }
|
11
|
-
let(:h2) { { a: 1, a1: 1, c: { c1: 2, c2: 'c2', c3: { d2: 'd2' } } } }
|
12
|
-
let(:expected_hash) { { a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } } } }
|
13
|
-
|
14
|
-
it 'deep merges two hashes' do
|
15
|
-
expect(h1.deep_merge(h2)).to eq expected_hash
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'deep merges another hash in place via bang method' do
|
19
|
-
h1.deep_merge!(h2)
|
20
|
-
expect(h1).to eq expected_hash
|
21
|
-
end
|
22
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::IgnoreUndeclared do
|
4
|
-
class ForgivingTrash < Hashie::Trash
|
5
|
-
include Hashie::Extensions::IgnoreUndeclared
|
6
|
-
property :city
|
7
|
-
property :state, from: :provence
|
8
|
-
end
|
9
|
-
|
10
|
-
subject { ForgivingTrash }
|
11
|
-
|
12
|
-
it 'silently ignores undeclared properties on initialization' do
|
13
|
-
expect { subject.new(city: 'Toronto', provence: 'ON', country: 'Canada') }.to_not raise_error
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'works with translated properties (with symbol keys)' do
|
17
|
-
expect(subject.new(provence: 'Ontario').state).to eq('Ontario')
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'works with translated properties (with string keys)' do
|
21
|
-
expect(subject.new(provence: 'Ontario').state).to eq('Ontario')
|
22
|
-
end
|
23
|
-
end
|
@@ -1,152 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::IndifferentAccess do
|
4
|
-
class IndifferentHashWithMergeInitializer < Hash
|
5
|
-
include Hashie::Extensions::MergeInitializer
|
6
|
-
include Hashie::Extensions::IndifferentAccess
|
7
|
-
|
8
|
-
class << self
|
9
|
-
alias_method :build, :new
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class IndifferentHashWithArrayInitializer < Hash
|
14
|
-
include Hashie::Extensions::IndifferentAccess
|
15
|
-
|
16
|
-
class << self
|
17
|
-
alias_method :build, :[]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class IndifferentHashWithTryConvertInitializer < Hash
|
22
|
-
include Hashie::Extensions::IndifferentAccess
|
23
|
-
|
24
|
-
class << self
|
25
|
-
alias_method :build, :try_convert
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
shared_examples_for 'hash with indifferent access' do
|
30
|
-
it 'is able to access via string or symbol' do
|
31
|
-
h = subject.build(abc: 123)
|
32
|
-
expect(h[:abc]).to eq 123
|
33
|
-
expect(h['abc']).to eq 123
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#values_at' do
|
37
|
-
it 'indifferently finds values' do
|
38
|
-
h = subject.build(:foo => 'bar', 'baz' => 'qux')
|
39
|
-
expect(h.values_at('foo', :baz)).to eq %w(bar qux)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#fetch' do
|
44
|
-
it 'works like normal fetch, but indifferent' do
|
45
|
-
h = subject.build(foo: 'bar')
|
46
|
-
expect(h.fetch(:foo)).to eq h.fetch('foo')
|
47
|
-
expect(h.fetch(:foo)).to eq 'bar'
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#delete' do
|
52
|
-
it 'deletes indifferently' do
|
53
|
-
h = subject.build(:foo => 'bar', 'baz' => 'qux')
|
54
|
-
h.delete('foo')
|
55
|
-
h.delete(:baz)
|
56
|
-
expect(h).to be_empty
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe '#key?' do
|
61
|
-
let(:h) { subject.build(foo: 'bar') }
|
62
|
-
|
63
|
-
it 'finds it indifferently' do
|
64
|
-
expect(h).to be_key(:foo)
|
65
|
-
expect(h).to be_key('foo')
|
66
|
-
end
|
67
|
-
|
68
|
-
%w(include? member? has_key?).each do |key_alias|
|
69
|
-
it "is aliased as #{key_alias}" do
|
70
|
-
expect(h.send(key_alias.to_sym, :foo)).to be(true)
|
71
|
-
expect(h.send(key_alias.to_sym, 'foo')).to be(true)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe '#update' do
|
77
|
-
let(:h) { subject.build(foo: 'bar') }
|
78
|
-
|
79
|
-
it 'allows keys to be indifferent still' do
|
80
|
-
h.update(baz: 'qux')
|
81
|
-
expect(h['foo']).to eq 'bar'
|
82
|
-
expect(h['baz']).to eq 'qux'
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'recursively injects indifference into sub-hashes' do
|
86
|
-
h.update(baz: { qux: 'abc' })
|
87
|
-
expect(h['baz']['qux']).to eq 'abc'
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'does not change the ancestors of the injected object class' do
|
91
|
-
h.update(baz: { qux: 'abc' })
|
92
|
-
expect(Hash.new).not_to be_respond_to(:indifferent_access?)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe '#replace' do
|
97
|
-
let(:h) { subject.build(foo: 'bar').replace(bar: 'baz', hi: 'bye') }
|
98
|
-
|
99
|
-
it 'returns self' do
|
100
|
-
expect(h).to be_a(subject)
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'removes old keys' do
|
104
|
-
[:foo, 'foo'].each do |k|
|
105
|
-
expect(h[k]).to be_nil
|
106
|
-
expect(h.key?(k)).to be false
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'creates new keys with indifferent access' do
|
111
|
-
[:bar, 'bar', :hi, 'hi'].each { |k| expect(h.key?(k)).to be true }
|
112
|
-
expect(h[:bar]).to eq 'baz'
|
113
|
-
expect(h['bar']).to eq 'baz'
|
114
|
-
expect(h[:hi]).to eq 'bye'
|
115
|
-
expect(h['hi']).to eq 'bye'
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe '#try_convert' do
|
120
|
-
describe 'with conversion' do
|
121
|
-
let(:h) { subject.try_convert(foo: 'bar') }
|
122
|
-
|
123
|
-
it 'is a subject' do
|
124
|
-
expect(h).to be_a(subject)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
describe 'without conversion' do
|
129
|
-
let(:h) { subject.try_convert('{ :foo => bar }') }
|
130
|
-
|
131
|
-
it 'is nil' do
|
132
|
-
expect(h).to be_nil
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
describe 'with merge initializer' do
|
139
|
-
subject { IndifferentHashWithMergeInitializer }
|
140
|
-
it_should_behave_like 'hash with indifferent access'
|
141
|
-
end
|
142
|
-
|
143
|
-
describe 'with array initializer' do
|
144
|
-
subject { IndifferentHashWithArrayInitializer }
|
145
|
-
it_should_behave_like 'hash with indifferent access'
|
146
|
-
end
|
147
|
-
|
148
|
-
describe 'with try convert initializer' do
|
149
|
-
subject { IndifferentHashWithTryConvertInitializer }
|
150
|
-
it_should_behave_like 'hash with indifferent access'
|
151
|
-
end
|
152
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Hashie::Extensions::KeyConversion do
|
4
|
-
subject do
|
5
|
-
klass = Class.new(::Hash)
|
6
|
-
klass.send :include, Hashie::Extensions::KeyConversion
|
7
|
-
klass
|
8
|
-
end
|
9
|
-
|
10
|
-
let(:instance) { subject.new }
|
11
|
-
|
12
|
-
describe '#stringify_keys!' do
|
13
|
-
it 'converts keys to strings' do
|
14
|
-
instance[:abc] = 'abc'
|
15
|
-
instance[123] = '123'
|
16
|
-
instance.stringify_keys!
|
17
|
-
expect((instance.keys & %w(abc 123)).size).to eq 2
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'performs deep conversion within nested hashes' do
|
21
|
-
instance[:ab] = subject.new
|
22
|
-
instance[:ab][:cd] = subject.new
|
23
|
-
instance[:ab][:cd][:ef] = 'abcdef'
|
24
|
-
instance.stringify_keys!
|
25
|
-
expect(instance).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'performs deep conversion within nested arrays' do
|
29
|
-
instance[:ab] = []
|
30
|
-
instance[:ab] << subject.new
|
31
|
-
instance[:ab] << subject.new
|
32
|
-
instance[:ab][0][:cd] = 'abcd'
|
33
|
-
instance[:ab][1][:ef] = 'abef'
|
34
|
-
instance.stringify_keys!
|
35
|
-
expect(instance).to eq('ab' => [{ 'cd' => 'abcd' }, { 'ef' => 'abef' }])
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'returns itself' do
|
39
|
-
expect(instance.stringify_keys!).to eq instance
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#stringify_keys' do
|
44
|
-
it 'converts keys to strings' do
|
45
|
-
instance[:abc] = 'def'
|
46
|
-
copy = instance.stringify_keys
|
47
|
-
expect(copy['abc']).to eq 'def'
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'does not alter the original' do
|
51
|
-
instance[:abc] = 'def'
|
52
|
-
copy = instance.stringify_keys
|
53
|
-
expect(instance.keys).to eq [:abc]
|
54
|
-
expect(copy.keys).to eq %w(abc)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe '#symbolize_keys!' do
|
59
|
-
it 'converts keys to symbols' do
|
60
|
-
instance['abc'] = 'abc'
|
61
|
-
instance['def'] = 'def'
|
62
|
-
instance.symbolize_keys!
|
63
|
-
expect((instance.keys & [:abc, :def]).size).to eq 2
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'performs deep conversion within nested hashes' do
|
67
|
-
instance['ab'] = subject.new
|
68
|
-
instance['ab']['cd'] = subject.new
|
69
|
-
instance['ab']['cd']['ef'] = 'abcdef'
|
70
|
-
instance.symbolize_keys!
|
71
|
-
expect(instance).to eq(ab: { cd: { ef: 'abcdef' } })
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'performs deep conversion within nested arrays' do
|
75
|
-
instance['ab'] = []
|
76
|
-
instance['ab'] << subject.new
|
77
|
-
instance['ab'] << subject.new
|
78
|
-
instance['ab'][0]['cd'] = 'abcd'
|
79
|
-
instance['ab'][1]['ef'] = 'abef'
|
80
|
-
instance.symbolize_keys!
|
81
|
-
expect(instance).to eq(ab: [{ cd: 'abcd' }, { ef: 'abef' }])
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'returns itself' do
|
85
|
-
expect(instance.symbolize_keys!).to eq instance
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
describe '#symbolize_keys' do
|
90
|
-
it 'converts keys to symbols' do
|
91
|
-
instance['abc'] = 'def'
|
92
|
-
copy = instance.symbolize_keys
|
93
|
-
expect(copy[:abc]).to eq 'def'
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'does not alter the original' do
|
97
|
-
instance['abc'] = 'def'
|
98
|
-
copy = instance.symbolize_keys
|
99
|
-
expect(instance.keys).to eq ['abc']
|
100
|
-
expect(copy.keys).to eq [:abc]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|