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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +518 -122
- data/CONTRIBUTING.md +24 -7
- data/LICENSE +1 -1
- data/README.md +455 -48
- data/Rakefile +18 -1
- data/UPGRADING.md +157 -7
- data/hashie.gemspec +14 -7
- data/lib/hashie/array.rb +21 -0
- data/lib/hashie/clash.rb +24 -12
- data/lib/hashie/dash.rb +56 -31
- 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 +91 -52
- data/lib/hashie/extensions/dash/coercion.rb +25 -0
- data/lib/hashie/extensions/dash/indifferent_access.rb +30 -1
- data/lib/hashie/extensions/dash/predefined_values.rb +88 -0
- data/lib/hashie/extensions/dash/property_translation.rb +59 -30
- data/lib/hashie/extensions/deep_fetch.rb +5 -3
- data/lib/hashie/extensions/deep_find.rb +14 -5
- data/lib/hashie/extensions/deep_locate.rb +40 -21
- data/lib/hashie/extensions/deep_merge.rb +28 -10
- data/lib/hashie/extensions/ignore_undeclared.rb +6 -4
- data/lib/hashie/extensions/indifferent_access.rb +49 -8
- data/lib/hashie/extensions/key_conflict_warning.rb +55 -0
- 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 +3 -1
- data/lib/hashie/extensions/mash/symbolize_keys.rb +38 -0
- data/lib/hashie/extensions/method_access.rb +77 -19
- data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +29 -5
- 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 +8 -5
- data/lib/hashie/extensions/symbolize_keys.rb +21 -7
- data/lib/hashie/hash.rb +18 -11
- data/lib/hashie/logger.rb +18 -0
- data/lib/hashie/mash.rb +196 -55
- data/lib/hashie/railtie.rb +21 -0
- data/lib/hashie/rash.rb +7 -7
- data/lib/hashie/utils.rb +44 -0
- data/lib/hashie/version.rb +1 -1
- data/lib/hashie.rb +34 -16
- metadata +30 -79
- data/spec/hashie/clash_spec.rb +0 -48
- data/spec/hashie/dash_spec.rb +0 -513
- data/spec/hashie/extensions/autoload_spec.rb +0 -24
- data/spec/hashie/extensions/coercion_spec.rb +0 -625
- data/spec/hashie/extensions/dash/indifferent_access_spec.rb +0 -84
- data/spec/hashie/extensions/deep_fetch_spec.rb +0 -97
- data/spec/hashie/extensions/deep_find_spec.rb +0 -45
- data/spec/hashie/extensions/deep_locate_spec.rb +0 -124
- data/spec/hashie/extensions/deep_merge_spec.rb +0 -45
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +0 -46
- data/spec/hashie/extensions/indifferent_access_spec.rb +0 -219
- data/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb +0 -208
- data/spec/hashie/extensions/key_conversion_spec.rb +0 -12
- data/spec/hashie/extensions/mash/safe_assignment_spec.rb +0 -23
- data/spec/hashie/extensions/merge_initializer_spec.rb +0 -23
- data/spec/hashie/extensions/method_access_spec.rb +0 -184
- data/spec/hashie/extensions/stringify_keys_spec.rb +0 -101
- data/spec/hashie/extensions/symbolize_keys_spec.rb +0 -106
- data/spec/hashie/hash_spec.rb +0 -84
- data/spec/hashie/mash_spec.rb +0 -683
- data/spec/hashie/parsers/yaml_erb_parser_spec.rb +0 -29
- data/spec/hashie/rash_spec.rb +0 -77
- data/spec/hashie/trash_spec.rb +0 -268
- data/spec/hashie/version_spec.rb +0 -7
- data/spec/spec_helper.rb +0 -15
- data/spec/support/module_context.rb +0 -11
- data/spec/support/ruby_version.rb +0 -10
data/spec/hashie/dash_spec.rb
DELETED
@@ -1,513 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
Hashie::Hash.class_eval do
|
4
|
-
def self.inherited(klass)
|
5
|
-
klass.instance_variable_set('@inheritance_test', true)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class DashTest < Hashie::Dash
|
10
|
-
property :first_name, required: true
|
11
|
-
property :email
|
12
|
-
property :count, default: 0
|
13
|
-
end
|
14
|
-
|
15
|
-
class DashNoRequiredTest < Hashie::Dash
|
16
|
-
property :first_name
|
17
|
-
property :email
|
18
|
-
property :count, default: 0
|
19
|
-
end
|
20
|
-
|
21
|
-
class DashWithCoercion < Hashie::Dash
|
22
|
-
include Hashie::Extensions::Coercion
|
23
|
-
property :person
|
24
|
-
property :city
|
25
|
-
|
26
|
-
coerce_key :person, ::DashNoRequiredTest
|
27
|
-
end
|
28
|
-
|
29
|
-
class PropertyBangTest < Hashie::Dash
|
30
|
-
property :important!
|
31
|
-
end
|
32
|
-
|
33
|
-
class SubclassedTest < DashTest
|
34
|
-
property :last_name, required: true
|
35
|
-
end
|
36
|
-
|
37
|
-
class RequiredMessageTest < DashTest
|
38
|
-
property :first_name, required: true, message: 'must be set.'
|
39
|
-
end
|
40
|
-
|
41
|
-
class DashDefaultTest < Hashie::Dash
|
42
|
-
property :aliases, default: ['Snake']
|
43
|
-
end
|
44
|
-
|
45
|
-
class DeferredTest < Hashie::Dash
|
46
|
-
property :created_at, default: proc { Time.now }
|
47
|
-
end
|
48
|
-
|
49
|
-
class DeferredWithSelfTest < Hashie::Dash
|
50
|
-
property :created_at, default: -> { Time.now }
|
51
|
-
property :updated_at, default: ->(test) { test.created_at }
|
52
|
-
end
|
53
|
-
|
54
|
-
describe DashTest do
|
55
|
-
def property_required_error(property)
|
56
|
-
[ArgumentError, "The property '#{property}' is required for #{subject.class.name}."]
|
57
|
-
end
|
58
|
-
|
59
|
-
def property_required_custom_error(property)
|
60
|
-
[ArgumentError, "The property '#{property}' must be set."]
|
61
|
-
end
|
62
|
-
|
63
|
-
def property_message_without_required_error
|
64
|
-
[ArgumentError, 'The :message option should be used with :required option.']
|
65
|
-
end
|
66
|
-
|
67
|
-
def no_property_error(property)
|
68
|
-
[NoMethodError, "The property '#{property}' is not defined for #{subject.class.name}."]
|
69
|
-
end
|
70
|
-
|
71
|
-
subject { DashTest.new(first_name: 'Bob', email: 'bob@example.com') }
|
72
|
-
let(:required_message) { RequiredMessageTest.new(first_name: 'Bob') }
|
73
|
-
|
74
|
-
it('subclasses Hashie::Hash') { should respond_to(:to_mash) }
|
75
|
-
|
76
|
-
describe '#to_s' do
|
77
|
-
subject { super().to_s }
|
78
|
-
it { should eq '#<DashTest count=0 email="bob@example.com" first_name="Bob">' }
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'lists all set properties in inspect' do
|
82
|
-
subject.first_name = 'Bob'
|
83
|
-
subject.email = 'bob@example.com'
|
84
|
-
expect(subject.inspect).to eq '#<DashTest count=0 email="bob@example.com" first_name="Bob">'
|
85
|
-
end
|
86
|
-
|
87
|
-
describe '#count' do
|
88
|
-
subject { super().count }
|
89
|
-
it { should be_zero }
|
90
|
-
end
|
91
|
-
|
92
|
-
it { should respond_to(:first_name) }
|
93
|
-
it { should respond_to(:first_name=) }
|
94
|
-
it { should_not respond_to(:nonexistent) }
|
95
|
-
|
96
|
-
it 'errors out for a non-existent property' do
|
97
|
-
expect { subject['nonexistent'] }.to raise_error(*no_property_error('nonexistent'))
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'errors out when attempting to set a required property to nil' do
|
101
|
-
expect { subject.first_name = nil }.to raise_error(*property_required_error('first_name'))
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'errors out when message added to not required property' do
|
105
|
-
expect do
|
106
|
-
class DashMessageOptionWithoutRequiredTest < Hashie::Dash
|
107
|
-
property :first_name, message: 'is required.'
|
108
|
-
end
|
109
|
-
end.to raise_error(*property_message_without_required_error)
|
110
|
-
|
111
|
-
expect do
|
112
|
-
class DashMessageOptionWithoutRequiredTest < Hashie::Dash
|
113
|
-
property :first_name, required: false, message: 'is required.'
|
114
|
-
end
|
115
|
-
end.to raise_error(*property_message_without_required_error)
|
116
|
-
end
|
117
|
-
|
118
|
-
context 'writing to properties' do
|
119
|
-
it 'fails writing a required property to nil' do
|
120
|
-
expect { subject.first_name = nil }.to raise_error(*property_required_error('first_name'))
|
121
|
-
expect { required_message.first_name = nil }.to raise_error(*property_required_custom_error('first_name'))
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'fails writing a required property to nil using []=' do
|
125
|
-
expect { subject[:first_name] = nil }.to raise_error(*property_required_error('first_name'))
|
126
|
-
expect { required_message[:first_name] = nil }.to raise_error(*property_required_custom_error('first_name'))
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'fails writing to a non-existent property using []=' do
|
130
|
-
expect { subject['nonexistent'] = 123 }.to raise_error(*no_property_error('nonexistent'))
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'works for an existing property using []=' do
|
134
|
-
subject[:first_name] = 'Bob'
|
135
|
-
expect(subject[:first_name]).to eq 'Bob'
|
136
|
-
expect { subject['first_name'] }.to raise_error(*no_property_error('first_name'))
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'works for an existing property using a method call' do
|
140
|
-
subject.first_name = 'Franklin'
|
141
|
-
expect(subject.first_name).to eq 'Franklin'
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
context 'reading from properties' do
|
146
|
-
it 'fails reading from a non-existent property using []' do
|
147
|
-
expect { subject['nonexistent'] }.to raise_error(*no_property_error('nonexistent'))
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'is able to retrieve properties through blocks' do
|
151
|
-
subject[:first_name] = 'Aiden'
|
152
|
-
value = nil
|
153
|
-
subject.[](:first_name) { |v| value = v }
|
154
|
-
expect(value).to eq 'Aiden'
|
155
|
-
end
|
156
|
-
|
157
|
-
it 'is able to retrieve properties through blocks with method calls' do
|
158
|
-
subject[:first_name] = 'Frodo'
|
159
|
-
value = nil
|
160
|
-
subject.first_name { |v| value = v }
|
161
|
-
expect(value).to eq 'Frodo'
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
context 'reading from deferred properties' do
|
166
|
-
it 'evaluates proc after initial read' do
|
167
|
-
expect(DeferredTest.new[:created_at]).to be_instance_of(Time)
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'does not evalute proc after subsequent reads' do
|
171
|
-
deferred = DeferredTest.new
|
172
|
-
expect(deferred[:created_at].object_id).to eq deferred[:created_at].object_id
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
context 'reading from a deferred property based on context' do
|
177
|
-
it 'provides the current hash as context for evaluation' do
|
178
|
-
deferred = DeferredWithSelfTest.new
|
179
|
-
expect(deferred[:created_at].object_id).to eq deferred[:created_at].object_id
|
180
|
-
expect(deferred[:updated_at].object_id).to eq deferred[:created_at].object_id
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
describe '#new' do
|
185
|
-
it 'fails with non-existent properties' do
|
186
|
-
expect { described_class.new(bork: '') }.to raise_error(*no_property_error('bork'))
|
187
|
-
end
|
188
|
-
|
189
|
-
it 'sets properties that it is able to' do
|
190
|
-
obj = described_class.new first_name: 'Michael'
|
191
|
-
expect(obj.first_name).to eq 'Michael'
|
192
|
-
end
|
193
|
-
|
194
|
-
it 'accepts nil' do
|
195
|
-
expect { DashNoRequiredTest.new(nil) }.not_to raise_error
|
196
|
-
end
|
197
|
-
|
198
|
-
it 'accepts block to define a global default' do
|
199
|
-
obj = described_class.new { |_, key| key.to_s.upcase }
|
200
|
-
expect(obj.first_name).to eq 'FIRST_NAME'
|
201
|
-
expect(obj.count).to be_zero
|
202
|
-
end
|
203
|
-
|
204
|
-
it 'fails when required values are missing' do
|
205
|
-
expect { DashTest.new }.to raise_error(*property_required_error('first_name'))
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'does not overwrite default values' do
|
209
|
-
obj1 = DashDefaultTest.new
|
210
|
-
obj1.aliases << 'El Rey'
|
211
|
-
obj2 = DashDefaultTest.new
|
212
|
-
expect(obj2.aliases).not_to include 'El Rey'
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
describe '#merge' do
|
217
|
-
it 'creates a new instance of the Dash' do
|
218
|
-
new_dash = subject.merge(first_name: 'Robert')
|
219
|
-
expect(subject.object_id).not_to eq new_dash.object_id
|
220
|
-
end
|
221
|
-
|
222
|
-
it 'merges the given hash' do
|
223
|
-
new_dash = subject.merge(first_name: 'Robert', email: 'robert@example.com')
|
224
|
-
expect(new_dash.first_name).to eq 'Robert'
|
225
|
-
expect(new_dash.email).to eq 'robert@example.com'
|
226
|
-
end
|
227
|
-
|
228
|
-
it 'fails with non-existent properties' do
|
229
|
-
expect { subject.merge(middle_name: 'James') }.to raise_error(*no_property_error('middle_name'))
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'errors out when attempting to set a required property to nil' do
|
233
|
-
expect { subject.merge(first_name: nil) }.to raise_error(*property_required_error('first_name'))
|
234
|
-
end
|
235
|
-
|
236
|
-
context 'given a block' do
|
237
|
-
it "sets merged key's values to the block's return value" do
|
238
|
-
expect(subject.merge(first_name: 'Jim') do |key, oldval, newval|
|
239
|
-
"#{key}: #{newval} #{oldval}"
|
240
|
-
end.first_name).to eq 'first_name: Jim Bob'
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
describe '#merge!' do
|
246
|
-
it 'modifies the existing instance of the Dash' do
|
247
|
-
original_dash = subject.merge!(first_name: 'Robert')
|
248
|
-
expect(subject.object_id).to eq original_dash.object_id
|
249
|
-
end
|
250
|
-
|
251
|
-
it 'merges the given hash' do
|
252
|
-
subject.merge!(first_name: 'Robert', email: 'robert@example.com')
|
253
|
-
expect(subject.first_name).to eq 'Robert'
|
254
|
-
expect(subject.email).to eq 'robert@example.com'
|
255
|
-
end
|
256
|
-
|
257
|
-
it 'fails with non-existent properties' do
|
258
|
-
expect { subject.merge!(middle_name: 'James') }.to raise_error(NoMethodError)
|
259
|
-
end
|
260
|
-
|
261
|
-
it 'errors out when attempting to set a required property to nil' do
|
262
|
-
expect { subject.merge!(first_name: nil) }.to raise_error(ArgumentError)
|
263
|
-
end
|
264
|
-
|
265
|
-
context 'given a block' do
|
266
|
-
it "sets merged key's values to the block's return value" do
|
267
|
-
expect(subject.merge!(first_name: 'Jim') do |key, oldval, newval|
|
268
|
-
"#{key}: #{newval} #{oldval}"
|
269
|
-
end.first_name).to eq 'first_name: Jim Bob'
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
describe 'properties' do
|
275
|
-
it 'lists defined properties' do
|
276
|
-
expect(described_class.properties).to eq Set.new([:first_name, :email, :count])
|
277
|
-
end
|
278
|
-
|
279
|
-
it 'checks if a property exists' do
|
280
|
-
expect(described_class.property?(:first_name)).to be_truthy
|
281
|
-
expect(described_class.property?('first_name')).to be_falsy
|
282
|
-
end
|
283
|
-
|
284
|
-
it 'checks if a property is required' do
|
285
|
-
expect(described_class.required?(:first_name)).to be_truthy
|
286
|
-
expect(described_class.required?('first_name')).to be_falsy
|
287
|
-
end
|
288
|
-
|
289
|
-
it 'doesnt include property from subclass' do
|
290
|
-
expect(described_class.property?(:last_name)).to be_falsy
|
291
|
-
end
|
292
|
-
|
293
|
-
it 'lists declared defaults' do
|
294
|
-
expect(described_class.defaults).to eq(count: 0)
|
295
|
-
end
|
296
|
-
|
297
|
-
it 'allows properties that end in bang' do
|
298
|
-
expect(PropertyBangTest.property?(:important!)).to be_truthy
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
describe '#replace' do
|
303
|
-
before { subject.replace(first_name: 'Cain') }
|
304
|
-
|
305
|
-
it 'return self' do
|
306
|
-
expect(subject.replace(email: 'bar').to_hash).to eq(email: 'bar', count: 0)
|
307
|
-
end
|
308
|
-
|
309
|
-
it 'sets all specified keys to their corresponding values' do
|
310
|
-
expect(subject.first_name).to eq 'Cain'
|
311
|
-
end
|
312
|
-
|
313
|
-
it 'leaves only specified keys and keys with default values' do
|
314
|
-
expect(subject.keys.sort_by(&:to_s)).to eq [:count, :first_name]
|
315
|
-
expect(subject.email).to be_nil
|
316
|
-
expect(subject.count).to eq 0
|
317
|
-
end
|
318
|
-
|
319
|
-
context 'when replacing keys with default values' do
|
320
|
-
before { subject.replace(count: 3) }
|
321
|
-
|
322
|
-
it 'sets all specified keys to their corresponding values' do
|
323
|
-
expect(subject.count).to eq 3
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
describe '#update_attributes!(params)' do
|
329
|
-
let(:params) { { first_name: 'Alice', email: 'alice@example.com' } }
|
330
|
-
|
331
|
-
context 'when there is coercion' do
|
332
|
-
let(:params_before) { { city: 'nyc', person: { first_name: 'Bob', email: 'bob@example.com' } } }
|
333
|
-
let(:params_after) { { city: 'sfo', person: { first_name: 'Alice', email: 'alice@example.com' } } }
|
334
|
-
|
335
|
-
subject { DashWithCoercion.new(params_before) }
|
336
|
-
|
337
|
-
it 'update the attributes' do
|
338
|
-
expect(subject.person.first_name).to eq params_before[:person][:first_name]
|
339
|
-
subject.update_attributes!(params_after)
|
340
|
-
expect(subject.person.first_name).to eq params_after[:person][:first_name]
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
it 'update the attributes' do
|
345
|
-
subject.update_attributes!(params)
|
346
|
-
expect(subject.first_name).to eq params[:first_name]
|
347
|
-
expect(subject.email).to eq params[:email]
|
348
|
-
expect(subject.count).to eq subject.class.defaults[:count]
|
349
|
-
end
|
350
|
-
|
351
|
-
context 'when required property is update to nil' do
|
352
|
-
let(:params) { { first_name: nil, email: 'alice@example.com' } }
|
353
|
-
|
354
|
-
it 'raise an ArgumentError' do
|
355
|
-
expect { subject.update_attributes!(params) }.to raise_error(ArgumentError)
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
context 'when a default property is update to nil' do
|
360
|
-
let(:params) { { count: nil, email: 'alice@example.com' } }
|
361
|
-
|
362
|
-
it 'set the property back to the default value' do
|
363
|
-
subject.update_attributes!(params)
|
364
|
-
expect(subject.email).to eq params[:email]
|
365
|
-
expect(subject.count).to eq subject.class.defaults[:count]
|
366
|
-
end
|
367
|
-
end
|
368
|
-
end
|
369
|
-
end
|
370
|
-
|
371
|
-
describe Hashie::Dash, 'inheritance' do
|
372
|
-
before do
|
373
|
-
@top = Class.new(Hashie::Dash)
|
374
|
-
@middle = Class.new(@top)
|
375
|
-
@bottom = Class.new(@middle)
|
376
|
-
end
|
377
|
-
|
378
|
-
it 'reports empty properties when nothing defined' do
|
379
|
-
expect(@top.properties).to be_empty
|
380
|
-
expect(@top.defaults).to be_empty
|
381
|
-
end
|
382
|
-
|
383
|
-
it 'inherits properties downwards' do
|
384
|
-
@top.property :echo
|
385
|
-
expect(@middle.properties).to include(:echo)
|
386
|
-
expect(@bottom.properties).to include(:echo)
|
387
|
-
end
|
388
|
-
|
389
|
-
it 'doesnt inherit properties upwards' do
|
390
|
-
@middle.property :echo
|
391
|
-
expect(@top.properties).not_to include(:echo)
|
392
|
-
expect(@bottom.properties).to include(:echo)
|
393
|
-
end
|
394
|
-
|
395
|
-
it 'allows overriding a default on an existing property' do
|
396
|
-
@top.property :echo
|
397
|
-
@middle.property :echo, default: 123
|
398
|
-
expect(@bottom.properties.to_a).to eq [:echo]
|
399
|
-
expect(@bottom.new.echo).to eq 123
|
400
|
-
end
|
401
|
-
|
402
|
-
it 'allows clearing an existing default' do
|
403
|
-
@top.property :echo
|
404
|
-
@middle.property :echo, default: 123
|
405
|
-
@bottom.property :echo
|
406
|
-
expect(@bottom.properties.to_a).to eq [:echo]
|
407
|
-
expect(@bottom.new.echo).to be_nil
|
408
|
-
end
|
409
|
-
|
410
|
-
it 'allows nil defaults' do
|
411
|
-
@bottom.property :echo, default: nil
|
412
|
-
expect(@bottom.new).to have_key(:echo)
|
413
|
-
expect(@bottom.new).to_not have_key('echo')
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
describe SubclassedTest do
|
418
|
-
subject { SubclassedTest.new(first_name: 'Bob', last_name: 'McNob', email: 'bob@example.com') }
|
419
|
-
|
420
|
-
describe '#count' do
|
421
|
-
subject { super().count }
|
422
|
-
it { should be_zero }
|
423
|
-
end
|
424
|
-
|
425
|
-
it { should respond_to(:first_name) }
|
426
|
-
it { should respond_to(:first_name=) }
|
427
|
-
it { should respond_to(:last_name) }
|
428
|
-
it { should respond_to(:last_name=) }
|
429
|
-
|
430
|
-
it 'has one additional property' do
|
431
|
-
expect(described_class.property?(:last_name)).to be_truthy
|
432
|
-
end
|
433
|
-
|
434
|
-
it "didn't override superclass inheritance logic" do
|
435
|
-
expect(described_class.instance_variable_get('@inheritance_test')).to be_truthy
|
436
|
-
end
|
437
|
-
end
|
438
|
-
|
439
|
-
class ConditionallyRequiredTest < Hashie::Dash
|
440
|
-
property :username
|
441
|
-
property :password, required: -> { !username.nil? }, message: 'must be set, too.'
|
442
|
-
end
|
443
|
-
|
444
|
-
describe ConditionallyRequiredTest do
|
445
|
-
it 'does not allow a conditionally required property to be set to nil if required' do
|
446
|
-
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: nil) }.to raise_error(ArgumentError, "The property 'password' must be set, too.")
|
447
|
-
end
|
448
|
-
|
449
|
-
it 'allows a conditionally required property to be set to nil if not required' do
|
450
|
-
expect { ConditionallyRequiredTest.new(username: nil, password: nil) }.not_to raise_error
|
451
|
-
end
|
452
|
-
|
453
|
-
it 'allows a conditionally required property to be set if required' do
|
454
|
-
expect { ConditionallyRequiredTest.new(username: 'bob.smith', password: '$ecure!') }.not_to raise_error
|
455
|
-
end
|
456
|
-
end
|
457
|
-
|
458
|
-
class MixedPropertiesTest < Hashie::Dash
|
459
|
-
property :symbol
|
460
|
-
property 'string'
|
461
|
-
end
|
462
|
-
|
463
|
-
describe MixedPropertiesTest do
|
464
|
-
subject { MixedPropertiesTest.new('string' => 'string', symbol: 'symbol') }
|
465
|
-
|
466
|
-
it { should respond_to('string') }
|
467
|
-
it { should respond_to(:symbol) }
|
468
|
-
|
469
|
-
it 'property?' do
|
470
|
-
expect(described_class.property?('string')).to be_truthy
|
471
|
-
expect(described_class.property?(:symbol)).to be_truthy
|
472
|
-
end
|
473
|
-
|
474
|
-
it 'fetch' do
|
475
|
-
expect(subject['string']).to eq('string')
|
476
|
-
expect { subject[:string] }.to raise_error(NoMethodError)
|
477
|
-
expect(subject[:symbol]).to eq('symbol')
|
478
|
-
expect { subject['symbol'] }.to raise_error(NoMethodError)
|
479
|
-
end
|
480
|
-
|
481
|
-
it 'double define' do
|
482
|
-
klass = Class.new(MixedPropertiesTest) do
|
483
|
-
property 'symbol'
|
484
|
-
end
|
485
|
-
instance = klass.new(symbol: 'one', 'symbol' => 'two')
|
486
|
-
expect(instance[:symbol]).to eq('one')
|
487
|
-
expect(instance['symbol']).to eq('two')
|
488
|
-
end
|
489
|
-
|
490
|
-
it 'assign' do
|
491
|
-
subject['string'] = 'updated'
|
492
|
-
expect(subject['string']).to eq('updated')
|
493
|
-
|
494
|
-
expect { subject[:string] = 'updated' }.to raise_error(NoMethodError)
|
495
|
-
|
496
|
-
subject[:symbol] = 'updated'
|
497
|
-
expect(subject[:symbol]).to eq('updated')
|
498
|
-
|
499
|
-
expect { subject['symbol'] = 'updated' }.to raise_error(NoMethodError)
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
context 'Dynamic Dash Class' do
|
504
|
-
it 'define property' do
|
505
|
-
klass = Class.new(Hashie::Dash)
|
506
|
-
my_property = 'my_property'
|
507
|
-
my_orig = my_property.dup
|
508
|
-
|
509
|
-
klass.property(my_property)
|
510
|
-
|
511
|
-
expect(my_property).to eq(my_orig)
|
512
|
-
end
|
513
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'hashie'
|
3
|
-
|
4
|
-
describe Hashie::Extensions do
|
5
|
-
describe 'autloads constants' do
|
6
|
-
it { is_expected.to be_const_defined(:MethodAccess) }
|
7
|
-
it { is_expected.to be_const_defined(:Coercion) }
|
8
|
-
it { is_expected.to be_const_defined(:DeepMerge) }
|
9
|
-
it { is_expected.to be_const_defined(:IgnoreUndeclared) }
|
10
|
-
it { is_expected.to be_const_defined(:IndifferentAccess) }
|
11
|
-
it { is_expected.to be_const_defined(:MergeInitializer) }
|
12
|
-
it { is_expected.to be_const_defined(:MethodAccess) }
|
13
|
-
it { is_expected.to be_const_defined(:MethodQuery) }
|
14
|
-
it { is_expected.to be_const_defined(:MethodReader) }
|
15
|
-
it { is_expected.to be_const_defined(:MethodWriter) }
|
16
|
-
it { is_expected.to be_const_defined(:StringifyKeys) }
|
17
|
-
it { is_expected.to be_const_defined(:SymbolizeKeys) }
|
18
|
-
it { is_expected.to be_const_defined(:DeepFetch) }
|
19
|
-
it { is_expected.to be_const_defined(:DeepFind) }
|
20
|
-
it { is_expected.to be_const_defined(:PrettyInspect) }
|
21
|
-
it { is_expected.to be_const_defined(:KeyConversion) }
|
22
|
-
it { is_expected.to be_const_defined(:MethodAccessWithOverride) }
|
23
|
-
end
|
24
|
-
end
|