hashie 4.0.0 → 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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +213 -187
  3. data/CONTRIBUTING.md +13 -6
  4. data/README.md +33 -9
  5. data/UPGRADING.md +5 -5
  6. data/hashie.gemspec +11 -6
  7. data/lib/hashie.rb +1 -0
  8. data/lib/hashie/extensions/dash/property_translation.rb +1 -1
  9. data/lib/hashie/extensions/deep_merge.rb +18 -1
  10. data/lib/hashie/extensions/mash/permissive_respond_to.rb +61 -0
  11. data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +19 -2
  12. data/lib/hashie/extensions/ruby_version_check.rb +5 -1
  13. data/lib/hashie/mash.rb +31 -26
  14. data/lib/hashie/utils.rb +28 -0
  15. data/lib/hashie/version.rb +1 -1
  16. metadata +16 -131
  17. data/spec/hashie/array_spec.rb +0 -29
  18. data/spec/hashie/clash_spec.rb +0 -70
  19. data/spec/hashie/dash_spec.rb +0 -608
  20. data/spec/hashie/extensions/autoload_spec.rb +0 -24
  21. data/spec/hashie/extensions/coercion_spec.rb +0 -648
  22. data/spec/hashie/extensions/dash/coercion_spec.rb +0 -13
  23. data/spec/hashie/extensions/dash/indifferent_access_spec.rb +0 -84
  24. data/spec/hashie/extensions/deep_fetch_spec.rb +0 -97
  25. data/spec/hashie/extensions/deep_find_spec.rb +0 -144
  26. data/spec/hashie/extensions/deep_locate_spec.rb +0 -138
  27. data/spec/hashie/extensions/deep_merge_spec.rb +0 -74
  28. data/spec/hashie/extensions/ignore_undeclared_spec.rb +0 -48
  29. data/spec/hashie/extensions/indifferent_access_spec.rb +0 -295
  30. data/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb +0 -208
  31. data/spec/hashie/extensions/key_conversion_spec.rb +0 -12
  32. data/spec/hashie/extensions/mash/define_accessors_spec.rb +0 -90
  33. data/spec/hashie/extensions/mash/keep_original_keys_spec.rb +0 -46
  34. data/spec/hashie/extensions/mash/safe_assignment_spec.rb +0 -50
  35. data/spec/hashie/extensions/mash/symbolize_keys_spec.rb +0 -39
  36. data/spec/hashie/extensions/merge_initializer_spec.rb +0 -23
  37. data/spec/hashie/extensions/method_access_spec.rb +0 -233
  38. data/spec/hashie/extensions/strict_key_access_spec.rb +0 -109
  39. data/spec/hashie/extensions/stringify_keys_spec.rb +0 -124
  40. data/spec/hashie/extensions/symbolize_keys_spec.rb +0 -131
  41. data/spec/hashie/hash_spec.rb +0 -123
  42. data/spec/hashie/mash_spec.rb +0 -1077
  43. data/spec/hashie/parsers/yaml_erb_parser_spec.rb +0 -46
  44. data/spec/hashie/rash_spec.rb +0 -83
  45. data/spec/hashie/trash_spec.rb +0 -334
  46. data/spec/hashie/utils_spec.rb +0 -25
  47. data/spec/hashie/version_spec.rb +0 -7
  48. data/spec/hashie_spec.rb +0 -13
  49. data/spec/integration/elasticsearch/integration_spec.rb +0 -41
  50. data/spec/integration/omniauth-oauth2/app.rb +0 -52
  51. data/spec/integration/omniauth-oauth2/integration_spec.rb +0 -26
  52. data/spec/integration/omniauth-oauth2/some_site.rb +0 -38
  53. data/spec/integration/omniauth/app.rb +0 -11
  54. data/spec/integration/omniauth/integration_spec.rb +0 -38
  55. data/spec/integration/rails-without-dependency/integration_spec.rb +0 -15
  56. data/spec/integration/rails/app.rb +0 -40
  57. data/spec/integration/rails/integration_spec.rb +0 -47
  58. data/spec/spec_helper.rb +0 -23
  59. data/spec/support/integration_specs.rb +0 -36
  60. data/spec/support/logger.rb +0 -24
  61. data/spec/support/module_context.rb +0 -11
  62. data/spec/support/ruby_version_check.rb +0 -6
@@ -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,90 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hashie::Extensions::Mash::DefineAccessors do
4
- let(:args) { [] }
5
-
6
- shared_examples 'class with dynamically defined accessors' do
7
- it 'defines reader on demand' do
8
- expect(subject.method_defined?(:foo)).to be_falsey
9
- instance.foo
10
- expect(subject.method_defined?(:foo)).to be_truthy
11
- end
12
-
13
- it 'defines writer on demand' do
14
- expect(subject.method_defined?(:foo=)).to be_falsey
15
- instance.foo = :bar
16
- expect(subject.method_defined?(:foo=)).to be_truthy
17
- end
18
-
19
- it 'defines predicate on demand' do
20
- expect(subject.method_defined?(:foo?)).to be_falsey
21
- instance.foo?
22
- expect(subject.method_defined?(:foo?)).to be_truthy
23
- end
24
-
25
- it 'defines initializing reader on demand' do
26
- expect(subject.method_defined?(:foo!)).to be_falsey
27
- instance.foo!
28
- expect(subject.method_defined?(:foo!)).to be_truthy
29
- end
30
-
31
- it 'defines underbang reader on demand' do
32
- expect(subject.method_defined?(:foo_)).to be_falsey
33
- instance.foo_
34
- expect(subject.method_defined?(:foo_)).to be_truthy
35
- end
36
-
37
- context 'when initializing from another hash' do
38
- let(:args) { [{ foo: :bar }] }
39
-
40
- it 'does not define any accessors' do
41
- expect(subject.method_defined?(:foo)).to be_falsey
42
- expect(subject.method_defined?(:foo=)).to be_falsey
43
- expect(subject.method_defined?(:foo?)).to be_falsey
44
- expect(subject.method_defined?(:foo!)).to be_falsey
45
- expect(subject.method_defined?(:foo_)).to be_falsey
46
- expect(instance.foo).to eq :bar
47
- end
48
- end
49
- end
50
-
51
- context 'when included in Mash subclass' do
52
- subject { Class.new(Hashie::Mash) { include Hashie::Extensions::Mash::DefineAccessors } }
53
- let(:instance) { subject.new(*args) }
54
-
55
- describe 'this subclass' do
56
- it_behaves_like 'class with dynamically defined accessors'
57
-
58
- describe 'when accessors are overrided in class' do
59
- before do
60
- subject.class_eval do
61
- def foo
62
- if self[:foo] != 1
63
- :bar
64
- else
65
- super
66
- end
67
- end
68
- end
69
- end
70
-
71
- it 'allows to call super' do
72
- expect(instance.foo).to eq :bar
73
- instance.foo = 2
74
- expect(instance.foo).to eq :bar
75
- instance.foo = 1
76
- expect(instance.foo).to eq 1
77
- end
78
- end
79
- end
80
- end
81
-
82
- context 'when Mash instance is extended' do
83
- let(:instance) { Hashie::Mash.new(*args).with_accessors! }
84
- subject { instance.singleton_class }
85
-
86
- describe 'its singleton class' do
87
- it_behaves_like 'class with dynamically defined accessors'
88
- end
89
- end
90
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Hashie::Extensions::Mash::KeepOriginalKeys do
4
- let(:keeping_mash) do
5
- Class.new(Hashie::Mash) do
6
- include Hashie::Extensions::Mash::KeepOriginalKeys
7
- end
8
- end
9
-
10
- it 'keeps the keys in the resulting hash identical to the original' do
11
- original = { :a => 'apple', 'b' => 'bottle' }
12
- mash = keeping_mash.new(original)
13
-
14
- expect(mash.to_hash).to eq(original)
15
- end
16
-
17
- it 'indifferently responds to keys' do
18
- original = { :a => 'apple', 'b' => 'bottle' }
19
- mash = keeping_mash.new(original)
20
-
21
- expect(mash['a']).to eq(mash[:a])
22
- expect(mash['b']).to eq(mash[:b])
23
- end
24
-
25
- it 'responds to all method accessors like a Mash' do
26
- original = { :a => 'apple', 'b' => 'bottle' }
27
- mash = keeping_mash.new(original)
28
-
29
- expect(mash.a).to eq('apple')
30
- expect(mash.a?).to eq(true)
31
- expect(mash.b).to eq('bottle')
32
- expect(mash.b?).to eq(true)
33
- expect(mash.underbang_).to be_a(keeping_mash)
34
- expect(mash.bang!).to be_a(keeping_mash)
35
- expect(mash.predicate?).to eq(false)
36
- end
37
-
38
- it 'keeps the keys that are directly passed without converting them' do
39
- original = { :a => 'apple', 'b' => 'bottle' }
40
- mash = keeping_mash.new(original)
41
-
42
- mash[:c] = 'cat'
43
- mash['d'] = 'dog'
44
- expect(mash.to_hash).to eq(:a => 'apple', 'b' => 'bottle', :c => 'cat', 'd' => 'dog')
45
- end
46
- end
@@ -1,50 +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
-
7
- private
8
-
9
- def my_own_private
10
- :hello!
11
- end
12
- end
13
-
14
- context 'when included in Mash' do
15
- subject { MashWithSafeAssignment.new }
16
-
17
- context 'when not attempting to override a method' do
18
- it 'assigns just fine' do
19
- expect do
20
- subject.blabla = 'Test'
21
- subject.blabla = 'Test'
22
- end.to_not raise_error
23
- end
24
- end
25
-
26
- context 'when attempting to override a method' do
27
- it 'raises an error' do
28
- expect { subject.zip = 'Test' }.to raise_error(ArgumentError)
29
- end
30
- end
31
-
32
- context 'when attempting to override a private method' do
33
- it 'raises an error' do
34
- expect { subject.my_own_private = 'Test' }.to raise_error(ArgumentError)
35
- end
36
- end
37
-
38
- context 'when attempting to initialize with predefined method' do
39
- it 'raises an error' do
40
- expect { MashWithSafeAssignment.new(zip: true) }.to raise_error(ArgumentError)
41
- end
42
- end
43
-
44
- context 'when setting as a hash key' do
45
- it 'still raises if conflicts with a method' do
46
- expect { subject[:zip] = 'Test' }.to raise_error(ArgumentError)
47
- end
48
- end
49
- end
50
- end
@@ -1,39 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Hashie::Extensions::Mash::SymbolizeKeys do
4
- it 'raises an error when included in a class that is not a Mash' do
5
- expect do
6
- Class.new do
7
- include Hashie::Extensions::Mash::SymbolizeKeys
8
- end
9
- end.to raise_error(ArgumentError)
10
- end
11
-
12
- it 'symbolizes all keys in the Mash' do
13
- my_mash = Class.new(Hashie::Mash) do
14
- include Hashie::Extensions::Mash::SymbolizeKeys
15
- end
16
-
17
- expect(my_mash.new('test' => 'value').to_h).to eq(test: 'value')
18
- end
19
-
20
- context 'implicit to_hash on double splat' do
21
- let(:destructure) { ->(**opts) { opts } }
22
- let(:my_mash) do
23
- Class.new(Hashie::Mash) do
24
- include Hashie::Extensions::Mash::SymbolizeKeys
25
- end
26
- end
27
- let(:instance) { my_mash.new('outer' => { 'inner' => 42 }, 'testing' => [1, 2, 3]) }
28
-
29
- subject { destructure.call(instance) }
30
-
31
- it 'is converted on method calls' do
32
- expect(subject).to eq(outer: { inner: 42 }, testing: [1, 2, 3])
33
- end
34
-
35
- it 'is converted on explicit operator call' do
36
- expect(**instance).to eq(outer: { inner: 42 }, testing: [1, 2, 3])
37
- end
38
- end
39
- 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,233 +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) # rubocop:disable Lint/BooleanSymbol
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).abc?).to eq true
96
- end
97
-
98
- it 'is true for non-nil symbol key values' do
99
- expect(subject.new(abc: 123).abc?).to eq true
100
- end
101
-
102
- it 'is false for false key values' do
103
- expect(subject.new(abc: false).abc?).to eq false
104
- end
105
-
106
- it 'is false for nil key values' do
107
- expect(subject.new(abc: nil).abc?).to eq false
108
- end
109
-
110
- it 'raises a NoMethodError for non-set keys' do
111
- expect { subject.new.abc? }.to raise_error(NoMethodError)
112
- end
113
-
114
- it '#respond_to? for existing string keys' do
115
- expect(subject.new('abc' => 'def')).to be_respond_to('abc?')
116
- end
117
-
118
- it '#respond_to? for existing symbol keys' do
119
- expect(subject.new(abc: 'def')).to be_respond_to(:abc?)
120
- end
121
-
122
- it 'does not #respond_to? for non-existent keys' do
123
- expect(subject.new).not_to be_respond_to('abc?')
124
- end
125
- end
126
-
127
- describe Hashie::Extensions::MethodAccess do
128
- it 'includes all of the other method mixins' do
129
- klass = Class.new(Hash)
130
- klass.send :include, Hashie::Extensions::MethodAccess
131
-
132
- included_modules = klass.ancestors & [
133
- Hashie::Extensions::MethodReader,
134
- Hashie::Extensions::MethodWriter,
135
- Hashie::Extensions::MethodQuery
136
- ]
137
-
138
- expect(included_modules.size).to eq 3
139
- end
140
- end
141
-
142
- describe Hashie::Extensions::MethodOverridingWriter do
143
- class OverridingHash < Hash
144
- include Hashie::Extensions::MethodOverridingWriter
145
- end
146
-
147
- subject { OverridingHash.new }
148
-
149
- it 'writes from a method call' do
150
- subject.awesome = 'sauce'
151
- expect(subject['awesome']).to eq 'sauce'
152
- end
153
-
154
- it 'convertes the key using the #convert_key method' do
155
- allow(subject).to receive(:convert_key).and_return(:awesome)
156
- subject.awesome = 'sauce'
157
- expect(subject[:awesome]).to eq 'sauce'
158
- end
159
-
160
- it 'raises NoMethodError on non equals-ending methods' do
161
- expect { subject.awesome }.to raise_error(NoMethodError)
162
- end
163
-
164
- it '#respond_to_missing? correctly' do
165
- expect(subject).to respond_to(:abc=)
166
- expect(subject).not_to respond_to(:abc)
167
- expect(subject.method(:abc=)).not_to be_nil
168
- end
169
-
170
- context 'when writing a Hash method' do
171
- before { subject.zip = 'a-dee-doo-dah' }
172
-
173
- it 'overrides the original method' do
174
- expect(subject.zip).to eq 'a-dee-doo-dah'
175
- end
176
-
177
- it 'aliases the method with two leading underscores' do
178
- expect(subject.__zip).to eq [[%w[zip a-dee-doo-dah]]]
179
- end
180
-
181
- it 'does not re-alias when overriding an already overridden method' do
182
- subject.zip = 'test'
183
- expect(subject.zip).to eq 'test'
184
- expect(subject.__zip).to eq [[%w[zip test]]]
185
- end
186
- end
187
- end
188
-
189
- describe Hashie::Extensions::MethodAccessWithOverride do
190
- it 'includes all of the other method mixins' do
191
- mod_list = [
192
- Hashie::Extensions::MethodReader,
193
- Hashie::Extensions::MethodOverridingWriter,
194
- Hashie::Extensions::MethodQuery,
195
- Hashie::Extensions::MethodOverridingInitializer
196
- ]
197
-
198
- klass = Class.new(Hash)
199
- klass.send :include, Hashie::Extensions::MethodAccessWithOverride
200
-
201
- expect((klass.ancestors & mod_list).size).to eq 4
202
- end
203
- end
204
-
205
- describe Hashie::Extensions::MethodOverridingInitializer do
206
- class OverridingHash < Hash
207
- include Hashie::Extensions::MethodOverridingInitializer
208
- end
209
-
210
- context 'when the key is a string' do
211
- subject { OverridingHash.new('zip' => 'a-dee-doo-dah') }
212
-
213
- it 'overrides the original method' do
214
- expect(subject.zip).to eq 'a-dee-doo-dah'
215
- end
216
-
217
- it 'aliases the method with two leading underscores' do
218
- expect(subject.__zip).to eq [[%w[zip a-dee-doo-dah]]]
219
- end
220
- end
221
-
222
- context 'when the key is a symbol' do
223
- subject { OverridingHash.new(zip: 'a-dee-doo-dah') }
224
-
225
- it 'overrides the original method' do
226
- expect(subject.zip).to eq 'a-dee-doo-dah'
227
- end
228
-
229
- it 'aliases the method with two leading underscores' do
230
- expect(subject.__zip).to eq [[%w[zip a-dee-doo-dah]]]
231
- end
232
- end
233
- end