hashie 3.4.2 → 5.0.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.
Files changed (73) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +518 -122
  3. data/CONTRIBUTING.md +24 -7
  4. data/LICENSE +1 -1
  5. data/README.md +455 -48
  6. data/Rakefile +18 -1
  7. data/UPGRADING.md +157 -7
  8. data/hashie.gemspec +14 -7
  9. data/lib/hashie/array.rb +21 -0
  10. data/lib/hashie/clash.rb +24 -12
  11. data/lib/hashie/dash.rb +56 -31
  12. data/lib/hashie/extensions/active_support/core_ext/hash.rb +14 -0
  13. data/lib/hashie/extensions/array/pretty_inspect.rb +19 -0
  14. data/lib/hashie/extensions/coercion.rb +91 -52
  15. data/lib/hashie/extensions/dash/coercion.rb +25 -0
  16. data/lib/hashie/extensions/dash/indifferent_access.rb +30 -1
  17. data/lib/hashie/extensions/dash/predefined_values.rb +88 -0
  18. data/lib/hashie/extensions/dash/property_translation.rb +59 -30
  19. data/lib/hashie/extensions/deep_fetch.rb +5 -3
  20. data/lib/hashie/extensions/deep_find.rb +14 -5
  21. data/lib/hashie/extensions/deep_locate.rb +40 -21
  22. data/lib/hashie/extensions/deep_merge.rb +28 -10
  23. data/lib/hashie/extensions/ignore_undeclared.rb +6 -4
  24. data/lib/hashie/extensions/indifferent_access.rb +49 -8
  25. data/lib/hashie/extensions/key_conflict_warning.rb +55 -0
  26. data/lib/hashie/extensions/mash/define_accessors.rb +90 -0
  27. data/lib/hashie/extensions/mash/keep_original_keys.rb +53 -0
  28. data/lib/hashie/extensions/mash/permissive_respond_to.rb +61 -0
  29. data/lib/hashie/extensions/mash/safe_assignment.rb +3 -1
  30. data/lib/hashie/extensions/mash/symbolize_keys.rb +38 -0
  31. data/lib/hashie/extensions/method_access.rb +77 -19
  32. data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +29 -5
  33. data/lib/hashie/extensions/ruby_version.rb +60 -0
  34. data/lib/hashie/extensions/ruby_version_check.rb +21 -0
  35. data/lib/hashie/extensions/strict_key_access.rb +77 -0
  36. data/lib/hashie/extensions/stringify_keys.rb +8 -5
  37. data/lib/hashie/extensions/symbolize_keys.rb +21 -7
  38. data/lib/hashie/hash.rb +18 -11
  39. data/lib/hashie/logger.rb +18 -0
  40. data/lib/hashie/mash.rb +196 -55
  41. data/lib/hashie/railtie.rb +21 -0
  42. data/lib/hashie/rash.rb +7 -7
  43. data/lib/hashie/utils.rb +44 -0
  44. data/lib/hashie/version.rb +1 -1
  45. data/lib/hashie.rb +34 -16
  46. metadata +30 -79
  47. data/spec/hashie/clash_spec.rb +0 -48
  48. data/spec/hashie/dash_spec.rb +0 -513
  49. data/spec/hashie/extensions/autoload_spec.rb +0 -24
  50. data/spec/hashie/extensions/coercion_spec.rb +0 -625
  51. data/spec/hashie/extensions/dash/indifferent_access_spec.rb +0 -84
  52. data/spec/hashie/extensions/deep_fetch_spec.rb +0 -97
  53. data/spec/hashie/extensions/deep_find_spec.rb +0 -45
  54. data/spec/hashie/extensions/deep_locate_spec.rb +0 -124
  55. data/spec/hashie/extensions/deep_merge_spec.rb +0 -45
  56. data/spec/hashie/extensions/ignore_undeclared_spec.rb +0 -46
  57. data/spec/hashie/extensions/indifferent_access_spec.rb +0 -219
  58. data/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb +0 -208
  59. data/spec/hashie/extensions/key_conversion_spec.rb +0 -12
  60. data/spec/hashie/extensions/mash/safe_assignment_spec.rb +0 -23
  61. data/spec/hashie/extensions/merge_initializer_spec.rb +0 -23
  62. data/spec/hashie/extensions/method_access_spec.rb +0 -184
  63. data/spec/hashie/extensions/stringify_keys_spec.rb +0 -101
  64. data/spec/hashie/extensions/symbolize_keys_spec.rb +0 -106
  65. data/spec/hashie/hash_spec.rb +0 -84
  66. data/spec/hashie/mash_spec.rb +0 -683
  67. data/spec/hashie/parsers/yaml_erb_parser_spec.rb +0 -29
  68. data/spec/hashie/rash_spec.rb +0 -77
  69. data/spec/hashie/trash_spec.rb +0 -268
  70. data/spec/hashie/version_spec.rb +0 -7
  71. data/spec/spec_helper.rb +0 -15
  72. data/spec/support/module_context.rb +0 -11
  73. data/spec/support/ruby_version.rb +0 -10
@@ -1,208 +0,0 @@
1
- # This set of tests verifies that Hashie::Extensions::IndifferentAccess works with
2
- # ActiveSupport HashWithIndifferentAccess hashes. See #164 and #166 for details.
3
-
4
- require 'active_support/hash_with_indifferent_access'
5
- require 'active_support/core_ext/hash'
6
- require 'spec_helper'
7
-
8
- describe Hashie::Extensions::IndifferentAccess do
9
- class IndifferentHashWithMergeInitializer < Hash
10
- include Hashie::Extensions::MergeInitializer
11
- include Hashie::Extensions::IndifferentAccess
12
-
13
- class << self
14
- alias_method :build, :new
15
- end
16
- end
17
-
18
- class IndifferentHashWithArrayInitializer < Hash
19
- include Hashie::Extensions::IndifferentAccess
20
-
21
- class << self
22
- alias_method :build, :[]
23
- end
24
- end
25
-
26
- class IndifferentHashWithTryConvertInitializer < Hash
27
- include Hashie::Extensions::IndifferentAccess
28
-
29
- class << self
30
- alias_method :build, :try_convert
31
- end
32
- end
33
-
34
- class CoercableHash < Hash
35
- include Hashie::Extensions::Coercion
36
- include Hashie::Extensions::MergeInitializer
37
- end
38
-
39
- class MashWithIndifferentAccess < Hashie::Mash
40
- include Hashie::Extensions::IndifferentAccess
41
- end
42
-
43
- shared_examples_for 'hash with indifferent access' do
44
- it 'is able to access via string or symbol' do
45
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: 123)
46
- h = subject.build(indifferent_hash)
47
- expect(h[:abc]).to eq 123
48
- expect(h['abc']).to eq 123
49
- end
50
-
51
- describe '#values_at' do
52
- it 'indifferently finds values' do
53
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
54
- :foo => 'bar', 'baz' => 'qux'
55
- )
56
- h = subject.build(indifferent_hash)
57
- expect(h.values_at('foo', :baz)).to eq %w(bar qux)
58
- end
59
- end
60
-
61
- describe '#fetch' do
62
- it 'works like normal fetch, but indifferent' do
63
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
64
- h = subject.build(indifferent_hash)
65
- expect(h.fetch(:foo)).to eq h.fetch('foo')
66
- expect(h.fetch(:foo)).to eq 'bar'
67
- end
68
- end
69
-
70
- describe '#delete' do
71
- it 'deletes indifferently' do
72
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
73
- :foo => 'bar',
74
- 'baz' => 'qux'
75
- )
76
- h = subject.build(indifferent_hash)
77
- h.delete('foo')
78
- h.delete(:baz)
79
- expect(h).to be_empty
80
- end
81
- end
82
-
83
- describe '#key?' do
84
- let(:h) do
85
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
86
- subject.build(indifferent_hash)
87
- end
88
-
89
- it 'finds it indifferently' do
90
- expect(h).to be_key(:foo)
91
- expect(h).to be_key('foo')
92
- end
93
-
94
- %w(include? member? has_key?).each do |key_alias|
95
- it "is aliased as #{key_alias}" do
96
- expect(h.send(key_alias.to_sym, :foo)).to be(true)
97
- expect(h.send(key_alias.to_sym, 'foo')).to be(true)
98
- end
99
- end
100
- end
101
-
102
- describe '#update' do
103
- let(:h) do
104
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
105
- subject.build(indifferent_hash)
106
- end
107
-
108
- it 'allows keys to be indifferent still' do
109
- h.update(baz: 'qux')
110
- expect(h['foo']).to eq 'bar'
111
- expect(h['baz']).to eq 'qux'
112
- end
113
-
114
- it 'recursively injects indifference into sub-hashes' do
115
- h.update(baz: { qux: 'abc' })
116
- expect(h['baz']['qux']).to eq 'abc'
117
- end
118
-
119
- it 'does not change the ancestors of the injected object class' do
120
- h.update(baz: { qux: 'abc' })
121
- expect(Hash.new).not_to be_respond_to(:indifferent_access?)
122
- end
123
- end
124
-
125
- describe '#replace' do
126
- let(:h) do
127
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
128
- subject.build(indifferent_hash).replace(bar: 'baz', hi: 'bye')
129
- end
130
-
131
- it 'returns self' do
132
- expect(h).to be_a(subject)
133
- end
134
-
135
- it 'removes old keys' do
136
- [:foo, 'foo'].each do |k|
137
- expect(h[k]).to be_nil
138
- expect(h.key?(k)).to be_falsy
139
- end
140
- end
141
-
142
- it 'creates new keys with indifferent access' do
143
- [:bar, 'bar', :hi, 'hi'].each { |k| expect(h.key?(k)).to be_truthy }
144
- expect(h[:bar]).to eq 'baz'
145
- expect(h['bar']).to eq 'baz'
146
- expect(h[:hi]).to eq 'bye'
147
- expect(h['hi']).to eq 'bye'
148
- end
149
- end
150
-
151
- describe '#try_convert' do
152
- describe 'with conversion' do
153
- let(:h) do
154
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
155
- subject.try_convert(indifferent_hash)
156
- end
157
-
158
- it 'is a subject' do
159
- expect(h).to be_a(subject)
160
- end
161
- end
162
-
163
- describe 'without conversion' do
164
- let(:h) { subject.try_convert('{ :foo => bar }') }
165
-
166
- it 'is nil' do
167
- expect(h).to be_nil
168
- end
169
- end
170
- end
171
- end
172
-
173
- describe 'with merge initializer' do
174
- subject { IndifferentHashWithMergeInitializer }
175
- it_should_behave_like 'hash with indifferent access'
176
- end
177
-
178
- describe 'with array initializer' do
179
- subject { IndifferentHashWithArrayInitializer }
180
- it_should_behave_like 'hash with indifferent access'
181
- end
182
-
183
- describe 'with try convert initializer' do
184
- subject { IndifferentHashWithTryConvertInitializer }
185
- it_should_behave_like 'hash with indifferent access'
186
- end
187
-
188
- describe 'with coercion' do
189
- subject { CoercableHash }
190
-
191
- let(:instance) { subject.new }
192
-
193
- it 'supports coercion for ActiveSupport::HashWithIndifferentAccess' do
194
- subject.coerce_key :foo, ActiveSupport::HashWithIndifferentAccess.new(Coercable => Coercable)
195
- instance[:foo] = { 'bar_key' => 'bar_value', 'bar2_key' => 'bar2_value' }
196
- expect(instance[:foo].keys).to all(be_coerced)
197
- expect(instance[:foo].values).to all(be_coerced)
198
- expect(instance[:foo]).to be_a(ActiveSupport::HashWithIndifferentAccess)
199
- end
200
- end
201
-
202
- describe 'Mash with indifferent access' do
203
- it 'is able to be created for a deep nested HashWithIndifferentAccess' do
204
- indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: { def: 123 })
205
- MashWithIndifferentAccess.new(indifferent_hash)
206
- end
207
- end
208
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/module_context'
3
-
4
- describe Hashie::Extensions::KeyConversion do
5
- include_context 'included hash module'
6
-
7
- it { should respond_to(:stringify_keys) }
8
- it { should respond_to(:stringify_keys!) }
9
-
10
- it { should respond_to(:symbolize_keys) }
11
- it { should respond_to(:symbolize_keys!) }
12
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hashie::Extensions::Mash::SafeAssignment do
4
- class MashWithSafeAssignment < Hashie::Mash
5
- include Hashie::Extensions::Mash::SafeAssignment
6
- end
7
-
8
- context 'when included in Mash' do
9
- subject { MashWithSafeAssignment.new }
10
-
11
- context 'when attempting to override a method' do
12
- it 'raises an error' do
13
- expect { subject.zip = 'Test' }.to raise_error(ArgumentError)
14
- end
15
- end
16
-
17
- context 'when setting as a hash key' do
18
- it 'still raises if conflicts with a method' do
19
- expect { subject[:zip] = 'Test' }.to raise_error(ArgumentError)
20
- end
21
- end
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hashie::Extensions::MergeInitializer do
4
- class MergeInitializerHash < Hash
5
- include Hashie::Extensions::MergeInitializer
6
- end
7
-
8
- subject { MergeInitializerHash }
9
-
10
- it 'initializes with no arguments' do
11
- expect(subject.new).to eq({})
12
- end
13
-
14
- it 'initializes with a hash' do
15
- expect(subject.new(abc: 'def')).to eq(abc: 'def')
16
- end
17
-
18
- it 'initializes with a hash and a default' do
19
- h = subject.new({ abc: 'def' }, 'bar')
20
- expect(h[:foo]).to eq 'bar'
21
- expect(h[:abc]).to eq 'def'
22
- end
23
- end
@@ -1,184 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hashie::Extensions::MethodReader do
4
- class ReaderHash < Hash
5
- include Hashie::Extensions::MethodReader
6
-
7
- def initialize(hash = {})
8
- update(hash)
9
- end
10
- end
11
-
12
- subject { ReaderHash }
13
-
14
- it 'reads string keys from the method' do
15
- expect(subject.new('awesome' => 'sauce').awesome).to eq 'sauce'
16
- end
17
-
18
- it 'reads symbol keys from the method' do
19
- expect(subject.new(awesome: 'sauce').awesome).to eq 'sauce'
20
- end
21
-
22
- it 'reads nil and false values out properly' do
23
- h = subject.new(nil: nil, false: false)
24
- expect(h.nil).to eq nil
25
- expect(h.false).to eq false
26
- end
27
-
28
- it 'raises a NoMethodError for undefined keys' do
29
- expect { subject.new.awesome }.to raise_error(NoMethodError)
30
- end
31
-
32
- it 'returns false for undefined keys if key with question has been called ' do
33
- expect(subject.new.awesome?).to eq false
34
- end
35
-
36
- it 'returns true for defined keys if key with question has been called' do
37
- expect(subject.new(awesome: 'sauce').awesome?).to eq true
38
- end
39
-
40
- describe '#respond_to?' do
41
- it 'is true for string keys' do
42
- expect(subject.new('awesome' => 'sauce')).to be_respond_to(:awesome)
43
- end
44
-
45
- it 'is true for symbol keys' do
46
- expect(subject.new(awesome: 'sauce')).to be_respond_to(:awesome)
47
- end
48
-
49
- it 'is false for non-keys' do
50
- expect(subject.new).not_to be_respond_to(:awesome)
51
- end
52
- end
53
- end
54
-
55
- describe Hashie::Extensions::MethodWriter do
56
- class WriterHash < Hash
57
- include Hashie::Extensions::MethodWriter
58
- end
59
-
60
- subject { WriterHash.new }
61
-
62
- it 'writes from a method call' do
63
- subject.awesome = 'sauce'
64
- expect(subject['awesome']).to eq 'sauce'
65
- end
66
-
67
- it 'converts the key using the #convert_key method' do
68
- allow(subject).to receive(:convert_key).and_return(:awesome)
69
- subject.awesome = 'sauce'
70
- expect(subject[:awesome]).to eq 'sauce'
71
- end
72
-
73
- it 'raises NoMethodError on non equals-ending methods' do
74
- expect { subject.awesome }.to raise_error(NoMethodError)
75
- end
76
-
77
- it '#respond_to? correctly' do
78
- expect(subject).to be_respond_to(:abc=)
79
- expect(subject).not_to be_respond_to(:abc)
80
- end
81
- end
82
-
83
- describe Hashie::Extensions::MethodQuery do
84
- class QueryHash < Hash
85
- include Hashie::Extensions::MethodQuery
86
-
87
- def initialize(hash = {})
88
- update(hash)
89
- end
90
- end
91
-
92
- subject { QueryHash }
93
-
94
- it 'is true for non-nil string key values' do
95
- expect(subject.new('abc' => 123)).to be_abc
96
- end
97
-
98
- it 'is true for non-nil symbol key values' do
99
- expect(subject.new(abc: 123)).to be_abc
100
- end
101
-
102
- it 'is false for nil key values' do
103
- expect(subject.new(abc: false)).not_to be_abc
104
- end
105
-
106
- it 'raises a NoMethodError for non-set keys' do
107
- expect { subject.new.abc? }.to raise_error(NoMethodError)
108
- end
109
-
110
- it '#respond_to? for existing string keys' do
111
- expect(subject.new('abc' => 'def')).to be_respond_to('abc?')
112
- end
113
-
114
- it '#respond_to? for existing symbol keys' do
115
- expect(subject.new(abc: 'def')).to be_respond_to(:abc?)
116
- end
117
-
118
- it 'does not #respond_to? for non-existent keys' do
119
- expect(subject.new).not_to be_respond_to('abc?')
120
- end
121
- end
122
-
123
- describe Hashie::Extensions::MethodAccess do
124
- it 'includes all of the other method mixins' do
125
- klass = Class.new(Hash)
126
- klass.send :include, Hashie::Extensions::MethodAccess
127
- expect((klass.ancestors & [Hashie::Extensions::MethodReader, Hashie::Extensions::MethodWriter, Hashie::Extensions::MethodQuery]).size).to eq 3
128
- end
129
- end
130
-
131
- describe Hashie::Extensions::MethodOverridingWriter do
132
- class OverridingHash < Hash
133
- include Hashie::Extensions::MethodOverridingWriter
134
- end
135
-
136
- subject { OverridingHash.new }
137
-
138
- it 'writes from a method call' do
139
- subject.awesome = 'sauce'
140
- expect(subject['awesome']).to eq 'sauce'
141
- end
142
-
143
- it 'convertes the key using the #convert_key method' do
144
- allow(subject).to receive(:convert_key).and_return(:awesome)
145
- subject.awesome = 'sauce'
146
- expect(subject[:awesome]).to eq 'sauce'
147
- end
148
-
149
- it 'raises NoMethodError on non equals-ending methods' do
150
- expect { subject.awesome }.to raise_error(NoMethodError)
151
- end
152
-
153
- it '#respond_to_missing? correctly' do
154
- expect(subject).to respond_to(:abc=)
155
- expect(subject).not_to respond_to(:abc)
156
- expect(subject.method(:abc=)).not_to be_nil
157
- end
158
-
159
- context 'when writing a Hash method' do
160
- before { subject.zip = 'a-dee-doo-dah' }
161
-
162
- it 'overrides the original method' do
163
- expect(subject.zip).to eq 'a-dee-doo-dah'
164
- end
165
-
166
- it 'aliases the method with two leading underscores' do
167
- expect(subject.__zip).to eq [[%w(zip a-dee-doo-dah)]]
168
- end
169
-
170
- it 'does not re-alias when overriding an already overridden method' do
171
- subject.zip = 'test'
172
- expect(subject.zip).to eq 'test'
173
- expect(subject.__zip).to eq [[%w(zip test)]]
174
- end
175
- end
176
- end
177
-
178
- describe Hashie::Extensions::MethodAccessWithOverride do
179
- it 'includes all of the other method mixins' do
180
- klass = Class.new(Hash)
181
- klass.send :include, Hashie::Extensions::MethodAccessWithOverride
182
- expect((klass.ancestors & [Hashie::Extensions::MethodReader, Hashie::Extensions::MethodOverridingWriter, Hashie::Extensions::MethodQuery]).size).to eq 3
183
- end
184
- end
@@ -1,101 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/module_context'
3
-
4
- def invoke(method)
5
- if subject == object
6
- subject.public_send(method)
7
- else
8
- subject.public_send(method, object)
9
- end
10
- end
11
-
12
- shared_examples 'stringify_keys!' do
13
- it 'converts keys to strings' do
14
- object[:abc] = 'abc'
15
- object[123] = '123'
16
- invoke :stringify_keys!
17
- expect((object.keys & %w(abc 123)).size).to eq 2
18
- end
19
-
20
- it 'converts nested instances of the same class' do
21
- object[:ab] = dummy_class.new
22
- object[:ab][:cd] = dummy_class.new
23
- object[:ab][:cd][:ef] = 'abcdef'
24
- invoke :stringify_keys!
25
- expect(object).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
26
- end
27
-
28
- it 'converts nested hashes' do
29
- object[:ab] = { cd: { ef: 'abcdef' } }
30
- invoke :stringify_keys!
31
- expect(object).to eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
32
- end
33
-
34
- it 'converts nested arrays' do
35
- object[:ab] = []
36
- object[:ab] << dummy_class.new
37
- object[:ab] << dummy_class.new
38
- object[:ab][0][:cd] = 'abcd'
39
- object[:ab][1][:ef] = 'abef'
40
- invoke :stringify_keys!
41
- expect(object).to eq('ab' => [{ 'cd' => 'abcd' }, { 'ef' => 'abef' }])
42
- end
43
- end
44
-
45
- shared_examples 'stringify_keys' do
46
- it 'converts keys to strings' do
47
- object[:abc] = 'def'
48
- copy = invoke :stringify_keys
49
- expect(copy['abc']).to eq 'def'
50
- end
51
-
52
- it 'does not alter the original' do
53
- object[:abc] = 'def'
54
- copy = invoke :stringify_keys
55
- expect(object.keys).to eq [:abc]
56
- expect(copy.keys).to eq %w(abc)
57
- end
58
- end
59
-
60
- describe Hashie::Extensions::StringifyKeys do
61
- include_context 'included hash module'
62
- let(:object) { subject }
63
-
64
- describe '#stringify_keys!' do
65
- include_examples 'stringify_keys!'
66
-
67
- it 'returns itself' do
68
- expect(subject.stringify_keys!).to eq subject
69
- end
70
- end
71
-
72
- context 'class methods' do
73
- subject { described_class }
74
- let(:object) { Hash.new }
75
-
76
- describe '.stringify_keys' do
77
- include_examples 'stringify_keys'
78
- end
79
- describe '.stringify_keys!' do
80
- include_examples 'stringify_keys!'
81
- end
82
- end
83
- end
84
-
85
- describe Hashie do
86
- let!(:dummy_class) do
87
- klass = Class.new(::Hash)
88
- klass.send :include, Hashie::Extensions::StringifyKeys
89
- klass
90
- end
91
-
92
- subject { described_class }
93
- let(:object) { Hash.new }
94
-
95
- describe '.stringify_keys' do
96
- include_examples 'stringify_keys'
97
- end
98
- describe '.stringify_keys!' do
99
- include_examples 'stringify_keys!'
100
- end
101
- end
@@ -1,106 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/module_context'
3
-
4
- def invoke(method)
5
- if subject == object
6
- subject.public_send(method)
7
- else
8
- subject.public_send(method, object)
9
- end
10
- end
11
-
12
- shared_examples 'symbolize_keys!' do
13
- it 'converts keys to symbols' do
14
- object['abc'] = 'abc'
15
- object['def'] = 'def'
16
- invoke :symbolize_keys!
17
- expect((object.keys & [:abc, :def]).size).to eq 2
18
- end
19
-
20
- it 'converts nested instances of the same class' do
21
- object['ab'] = dummy_class.new
22
- object['ab']['cd'] = dummy_class.new
23
- object['ab']['cd']['ef'] = 'abcdef'
24
- invoke :symbolize_keys!
25
- expect(object).to eq(ab: { cd: { ef: 'abcdef' } })
26
- end
27
-
28
- it 'converts nested hashes' do
29
- object['ab'] = { 'cd' => { 'ef' => 'abcdef' } }
30
- invoke :symbolize_keys!
31
- expect(object).to eq(ab: { cd: { ef: 'abcdef' } })
32
- end
33
-
34
- it 'performs deep conversion within nested arrays' do
35
- object['ab'] = []
36
- object['ab'] << dummy_class.new
37
- object['ab'] << dummy_class.new
38
- object['ab'][0]['cd'] = 'abcd'
39
- object['ab'][1]['ef'] = 'abef'
40
- new_object = invoke :symbolize_keys
41
- expect(new_object).to eq(ab: [{ cd: 'abcd' }, { ef: 'abef' }])
42
- end
43
- end
44
-
45
- shared_examples 'symbolize_keys' do
46
- it 'converts keys to symbols' do
47
- object['abc'] = 'def'
48
- copy = invoke :symbolize_keys
49
- expect(copy[:abc]).to eq 'def'
50
- end
51
-
52
- it 'does not alter the original' do
53
- object['abc'] = 'def'
54
- copy = invoke :symbolize_keys
55
- expect(object.keys).to eq ['abc']
56
- expect(copy.keys).to eq [:abc]
57
- end
58
- end
59
-
60
- describe Hashie::Extensions::SymbolizeKeys do
61
- include_context 'included hash module'
62
- let(:object) { subject }
63
-
64
- describe '#symbolize_keys!' do
65
- include_examples 'symbolize_keys!'
66
- let(:object) { subject }
67
-
68
- it 'returns itself' do
69
- expect(subject.symbolize_keys!).to eq subject
70
- end
71
- end
72
-
73
- describe '#symbolize_keys' do
74
- include_examples 'symbolize_keys'
75
- end
76
-
77
- context 'class methods' do
78
- subject { described_class }
79
- let(:object) { Hash.new }
80
-
81
- describe '.symbolize_keys' do
82
- include_examples 'symbolize_keys'
83
- end
84
- describe '.symbolize_keys!' do
85
- include_examples 'symbolize_keys!'
86
- end
87
- end
88
- end
89
-
90
- describe Hashie do
91
- let!(:dummy_class) do
92
- klass = Class.new(::Hash)
93
- klass.send :include, Hashie::Extensions::StringifyKeys
94
- klass
95
- end
96
-
97
- subject { described_class }
98
- let(:object) { Hash.new }
99
-
100
- describe '.symbolize_keys' do
101
- include_examples 'symbolize_keys'
102
- end
103
- describe '.symbolize_keys!' do
104
- include_examples 'symbolize_keys!'
105
- end
106
- end