attributor 5.0.2 → 5.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -0
  3. data/.travis.yml +6 -4
  4. data/CHANGELOG.md +6 -1
  5. data/Gemfile +1 -1
  6. data/Guardfile +14 -8
  7. data/Rakefile +4 -5
  8. data/attributor.gemspec +34 -29
  9. data/lib/attributor.rb +23 -29
  10. data/lib/attributor/attribute.rb +108 -127
  11. data/lib/attributor/attribute_resolver.rb +12 -26
  12. data/lib/attributor/dsl_compiler.rb +17 -21
  13. data/lib/attributor/dumpable.rb +1 -2
  14. data/lib/attributor/example_mixin.rb +5 -8
  15. data/lib/attributor/exceptions.rb +5 -6
  16. data/lib/attributor/extensions/randexp.rb +3 -5
  17. data/lib/attributor/extras/field_selector.rb +4 -4
  18. data/lib/attributor/extras/field_selector/transformer.rb +6 -7
  19. data/lib/attributor/families/numeric.rb +0 -2
  20. data/lib/attributor/families/temporal.rb +1 -4
  21. data/lib/attributor/hash_dsl_compiler.rb +22 -25
  22. data/lib/attributor/type.rb +24 -32
  23. data/lib/attributor/types/bigdecimal.rb +7 -14
  24. data/lib/attributor/types/boolean.rb +5 -8
  25. data/lib/attributor/types/class.rb +9 -10
  26. data/lib/attributor/types/collection.rb +34 -44
  27. data/lib/attributor/types/container.rb +9 -15
  28. data/lib/attributor/types/csv.rb +7 -10
  29. data/lib/attributor/types/date.rb +20 -25
  30. data/lib/attributor/types/date_time.rb +7 -14
  31. data/lib/attributor/types/float.rb +4 -6
  32. data/lib/attributor/types/hash.rb +171 -196
  33. data/lib/attributor/types/ids.rb +2 -6
  34. data/lib/attributor/types/integer.rb +12 -17
  35. data/lib/attributor/types/model.rb +39 -48
  36. data/lib/attributor/types/object.rb +2 -4
  37. data/lib/attributor/types/polymorphic.rb +118 -0
  38. data/lib/attributor/types/regexp.rb +4 -5
  39. data/lib/attributor/types/string.rb +6 -7
  40. data/lib/attributor/types/struct.rb +8 -15
  41. data/lib/attributor/types/symbol.rb +3 -6
  42. data/lib/attributor/types/tempfile.rb +5 -6
  43. data/lib/attributor/types/time.rb +11 -11
  44. data/lib/attributor/types/uri.rb +9 -10
  45. data/lib/attributor/version.rb +1 -1
  46. data/spec/attribute_resolver_spec.rb +57 -78
  47. data/spec/attribute_spec.rb +174 -216
  48. data/spec/attributor_spec.rb +11 -15
  49. data/spec/dsl_compiler_spec.rb +19 -33
  50. data/spec/dumpable_spec.rb +6 -7
  51. data/spec/extras/field_selector/field_selector_spec.rb +1 -1
  52. data/spec/families_spec.rb +1 -3
  53. data/spec/hash_dsl_compiler_spec.rb +65 -74
  54. data/spec/spec_helper.rb +9 -3
  55. data/spec/support/hashes.rb +2 -3
  56. data/spec/support/models.rb +30 -36
  57. data/spec/support/polymorphics.rb +10 -0
  58. data/spec/type_spec.rb +38 -61
  59. data/spec/types/bigdecimal_spec.rb +11 -15
  60. data/spec/types/boolean_spec.rb +12 -39
  61. data/spec/types/class_spec.rb +10 -11
  62. data/spec/types/collection_spec.rb +72 -81
  63. data/spec/types/container_spec.rb +22 -26
  64. data/spec/types/csv_spec.rb +15 -16
  65. data/spec/types/date_spec.rb +16 -33
  66. data/spec/types/date_time_spec.rb +16 -33
  67. data/spec/types/file_upload_spec.rb +1 -2
  68. data/spec/types/float_spec.rb +7 -14
  69. data/spec/types/hash_spec.rb +285 -289
  70. data/spec/types/ids_spec.rb +5 -7
  71. data/spec/types/integer_spec.rb +37 -46
  72. data/spec/types/model_spec.rb +111 -128
  73. data/spec/types/polymorphic_spec.rb +134 -0
  74. data/spec/types/regexp_spec.rb +4 -7
  75. data/spec/types/string_spec.rb +17 -21
  76. data/spec/types/struct_spec.rb +40 -47
  77. data/spec/types/tempfile_spec.rb +1 -2
  78. data/spec/types/temporal_spec.rb +9 -0
  79. data/spec/types/time_spec.rb +16 -32
  80. data/spec/types/type_spec.rb +15 -0
  81. data/spec/types/uri_spec.rb +6 -7
  82. metadata +77 -25
@@ -1,8 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
2
 
3
-
4
3
  describe Attributor::Hash do
5
-
6
4
  subject(:type) { Attributor::Hash }
7
5
 
8
6
  its(:native_type) { should be(type) }
@@ -16,45 +14,63 @@ describe Attributor::Hash do
16
14
  Class.new(Attributor::Model) do
17
15
  attributes do
18
16
  raise 'sorry :('
19
- attribute :name, String
20
17
  end
21
18
  end
22
19
  end
23
20
 
24
21
  it 'throws original exception upon first run' do
25
- lambda {
22
+ expect do
26
23
  broken_model.attributes
27
- }.should raise_error(RuntimeError, 'sorry :(')
24
+ end.to raise_error(RuntimeError, 'sorry :(')
28
25
  end
26
+ context 'subsequent use' do
27
+ before do
28
+ expect do
29
+ broken_model.attributes
30
+ end.to raise_error(RuntimeError, 'sorry :(')
31
+ end
29
32
 
30
- it 'throws InvalidDefinition for subsequent access' do
31
- broken_model.attributes rescue nil
32
-
33
- lambda {
34
- broken_model.attributes
35
- }.should raise_error(Attributor::InvalidDefinition)
36
- end
33
+ it 'throws InvalidDefinition for subsequent access' do
34
+ expect do
35
+ broken_model.attributes
36
+ end.to raise_error(Attributor::InvalidDefinition)
37
+ end
37
38
 
38
- it 'throws for any attempts at using of an instance of it' do
39
- broken_model.attributes rescue nil
39
+ it 'throws for any attempts at using of an instance of it' do
40
+ instance = broken_model.new
41
+ expect do
42
+ instance.name
43
+ end.to raise_error(Attributor::InvalidDefinition)
44
+ end
40
45
 
41
- instance = broken_model.new
42
- lambda {
43
- instance.name
44
- }.should raise_error(Attributor::InvalidDefinition)
46
+ context 'for a type with a name' do
47
+ subject(:broken_model) do
48
+ Class.new(Attributor::Model) do
49
+ def self.name
50
+ 'BrokenModel'
51
+ end
52
+ attributes do
53
+ raise 'sorry :('
54
+ end
55
+ end
56
+ end
57
+ it 'includes the correct type.name if applicable' do
58
+ expect do
59
+ broken_model.attributes
60
+ end.to raise_error(Attributor::InvalidDefinition, /BrokenModel/)
61
+ end
62
+ end
45
63
  end
46
-
47
64
  end
48
65
  end
49
66
 
50
67
  context 'default options' do
51
68
  subject(:options) { type.options }
52
69
  it 'has allow_extra false' do
53
- options[:allow_extra].should be(false)
70
+ expect(options[:allow_extra]).to be(false)
54
71
  end
55
72
  end
56
73
 
57
-
58
74
  context '.example' do
59
75
  context 'for a simple hash' do
60
76
  subject(:example) { Attributor::Hash.example }
@@ -65,12 +81,12 @@ describe Attributor::Hash do
65
81
  end
66
82
 
67
83
  context 'for a typed hash' do
68
- subject(:example){ Attributor::Hash.of(value: Integer).example}
84
+ subject(:example) { Attributor::Hash.of(value: Integer).example }
69
85
 
70
86
  it 'returns a hash with keys and/or values of the right type' do
71
- example.should be_kind_of(Attributor::Hash)
72
- example.keys.size.should > 0
73
- example.values.all? {|v| v.kind_of? Integer}.should be(true)
87
+ expect(example).to be_kind_of(Attributor::Hash)
88
+ expect(example.keys.size).to be > 0
89
+ expect(example.values.all? { |v| v.is_a? Integer }).to be(true)
74
90
  end
75
91
  end
76
92
 
@@ -81,128 +97,129 @@ describe Attributor::Hash do
81
97
  subject(:example) { HashWithStrings.example(name: name, something: something) }
82
98
 
83
99
  context 'resolves a lazy attributes on demand' do
84
- before { example.lazy_attributes.keys.should eq [:name, :something] }
85
- after { example.lazy_attributes.keys.should eq [:something] }
100
+ before { expect(example.lazy_attributes.keys).to eq [:name, :something] }
101
+ after { expect(example.lazy_attributes.keys).to eq [:something] }
86
102
 
87
103
  it 'using get' do
88
- example.get(:name).should be name
104
+ expect(example.get(:name)).to be name
89
105
  end
90
106
  it 'using []' do
91
- example[:name].should be name
107
+ expect(example[:name]).to be name
92
108
  end
93
109
 
94
110
  it 'using set' do
95
111
  example.set :name, 'not bob'
96
- example.get(:name).should == 'not bob'
112
+ expect(example.get(:name)).to eq 'not bob'
97
113
  end
98
114
  it 'using []=' do
99
115
  example[:name] = 'not bob'
100
- example[:name].should == 'not bob'
116
+ expect(example[:name]).to eq 'not bob'
101
117
  end
102
118
  end
103
119
 
104
120
  its(:size) { should eq 2 }
105
- its(:values) { should =~ [name, something] }
106
- its(:keys) { should =~ [:name, :something] }
121
+ its(:values) { should match_array [name, something] }
122
+ its(:keys) { should match_array [:name, :something] }
107
123
  it do
108
124
  should_not be_empty
109
125
  end
110
126
 
111
127
  it 'responds to key? correctly' do
112
- example.key?(:name).should be(true)
113
- example.key?(:something).should be(true)
128
+ expect(example.key?(:name)).to be(true)
129
+ expect(example.key?(:something)).to be(true)
114
130
  end
115
131
 
116
132
  it 'enumerates the contents' do
117
- example.collect {|k,v| k }.should eq [:name, :something ]
133
+ expect(example.collect { |k, _v| k }).to eq [:name, :something]
118
134
  end
119
135
 
120
136
  it 'enumerates the contents using each_pair' do
121
137
  pairs = []
122
- example.each_pair {|pair| pairs << pair }
123
- pairs.should =~ [ [:name, name], [:something, something] ]
138
+ example.each_pair { |pair| pairs << pair }
139
+ expect(pairs).to match_array [[:name, name], [:something, something]]
124
140
  end
125
141
 
126
- its(:contents){ should eq ({name: name, something: something}) }
142
+ its(:contents) { should eq(name: name, something: something) }
127
143
  it 'does not create methods for the keys' do
128
- example.should_not respond_to(:name)
129
- example.should_not respond_to(:something)
144
+ expect(example).not_to respond_to(:name)
145
+ expect(example).not_to respond_to(:something)
130
146
  end
131
-
132
147
  end
133
148
 
134
149
  context 'using a non array context' do
135
150
  it 'should work for hashes with key/value types' do
136
- expect{ Attributor::Hash.of(key:String,value:String).example("Not an Array") }.to_not raise_error
151
+ expect do
152
+ Attributor::Hash.of(key: String, value: String)
153
+ .example('Not an Array')
154
+ end.to_not raise_error
137
155
  end
138
156
  it 'should work for hashes with keys defined' do
139
157
  block = proc { key 'a string', String }
140
- hash = Attributor::Hash.of(key:String).construct(block)
158
+ hash = Attributor::Hash.of(key: String).construct(block)
141
159
 
142
- expect{ hash.example("Not an Array") }.to_not raise_error
160
+ expect { hash.example('Not an Array') }.to_not raise_error
143
161
  end
144
162
  end
145
163
  end
146
164
 
147
165
  context '.load' do
148
- let(:value) { {one: 'two', three: 4} }
166
+ let(:value) { { one: 'two', three: 4 } }
149
167
  subject(:hash) { type.load(value) }
150
168
 
151
169
  context 'for nil with recurse: true' do
152
170
  let(:value) { nil }
153
- subject(:hash) { HashWithModel.load(value, recurse:true) }
171
+ subject(:hash) { HashWithModel.load(value, recurse: true) }
154
172
 
155
173
  it 'works' do
156
- hash[:name].should eq('Turkey McDucken')
157
- hash[:chicken].age.should eq(1)
174
+ expect(hash[:name]).to eq('Turkey McDucken')
175
+ expect(hash[:chicken].age).to eq(1)
158
176
  end
159
177
  end
160
178
 
161
179
  context 'for a simple hash' do
162
180
  it { should eq(value) }
163
181
  it 'equals the hash' do
164
- hash.should eq value
165
- hash[:one].should eq('two')
166
- hash[:three].should eq(4)
182
+ expect(hash).to eq value
183
+ expect(hash[:one]).to eq('two')
184
+ expect(hash[:three]).to eq(4)
167
185
  end
168
186
  end
169
187
 
170
188
  context 'for a JSON encoded hash' do
171
- let(:value_as_hash) { {'one' => 'two', 'three' => 4} }
172
- let(:value) { JSON.dump( value_as_hash ) }
189
+ let(:value_as_hash) { { 'one' => 'two', 'three' => 4 } }
190
+ let(:value) { JSON.dump(value_as_hash) }
173
191
  it 'deserializes and converts it to a real hash' do
174
- hash.should eq(value_as_hash)
175
- hash['one'].should eq 'two'
192
+ expect(hash).to eq(value_as_hash)
193
+ expect(hash['one']).to eq 'two'
176
194
  end
177
195
  end
178
196
 
179
197
  context 'for a typed hash' do
180
- subject(:type){ Attributor::Hash.of(key: String, value: Integer)}
198
+ subject(:type) { Attributor::Hash.of(key: String, value: Integer) }
181
199
  context 'with good values' do
182
- let(:value) { {one: '1', 'three' => 3} }
200
+ let(:value) { { one: '1', 'three' => 3 } }
183
201
  it 'coerces good values into the correct types' do
184
- hash.should eq({'one' => 1, 'three' => 3})
185
- hash['one'].should eq(1)
202
+ expect(hash).to eq('one' => 1, 'three' => 3)
203
+ expect(hash['one']).to eq(1)
186
204
  end
187
205
  end
188
206
 
189
207
  context 'with incompatible values' do
190
- let(:value) { {one: 'two', three: 4} }
208
+ let(:value) { { one: 'two', three: 4 } }
191
209
  it 'fails' do
192
- expect{
210
+ expect do
193
211
  type.load(value)
194
- }.to raise_error(/invalid value for Integer/)
212
+ end.to raise_error(/invalid value for Integer/)
195
213
  end
196
214
  end
197
-
198
215
  end
199
216
 
200
217
  context 'for a partially typed hash' do
201
- subject(:type){ Attributor::Hash.of(value: Integer) }
218
+ subject(:type) { Attributor::Hash.of(value: Integer) }
202
219
  context 'with good values' do
203
- let(:value) { {one: '1', [1,2,3] => 3} }
220
+ let(:value) { { one: '1', [1, 2, 3] => 3 } }
204
221
  it 'coerces only values into the correct types (and leave keys alone)' do
205
- hash.should eq({:one => 1, [1,2,3] => 3})
222
+ expect(hash).to eq(:one => 1, [1, 2, 3] => 3)
206
223
  end
207
224
  end
208
225
  end
@@ -222,20 +239,20 @@ describe Attributor::Hash do
222
239
  Class.new(Attributor::Hash) do
223
240
  keys do
224
241
  key 'id', Integer
225
- key 'name', String, default: "unnamed"
242
+ key 'name', String, default: 'unnamed'
226
243
  key 'chicken', Chicken
227
244
  end
228
245
  end
229
246
  end
230
247
 
231
- let(:value) { {'chicken' => Chicken.example} }
248
+ let(:value) { { 'chicken' => Chicken.example } }
232
249
 
233
250
  subject(:hash) { type.load(value) }
234
251
 
235
252
  it { should_not have_key('id') }
236
253
  it 'has the defaulted key' do
237
- hash.should have_key('name')
238
- hash['name'].should eq('unnamed')
254
+ expect(hash).to have_key('name')
255
+ expect(hash['name']).to eq('unnamed')
239
256
  end
240
257
  end
241
258
 
@@ -273,44 +290,39 @@ describe Attributor::Hash do
273
290
  end
274
291
 
275
292
  it 'complains about an unknown key' do
276
- expect {
293
+ expect do
277
294
  loader_hash.load(value)
278
- }.to raise_error(Attributor::AttributorException,/Unknown key received: :weird_key/)
295
+ end.to raise_error(Attributor::AttributorException,
296
+ /Unknown key received: :weird_key/)
279
297
  end
280
298
  end
281
299
  end
282
300
  end
283
-
284
-
285
301
  end
286
302
 
287
-
288
303
  context '.of' do
289
304
  context 'specific key and value types' do
290
- let(:key_type){ String }
291
- let(:value_type){ Integer }
305
+ let(:key_type) { String }
306
+ let(:value_type) { Integer }
292
307
 
293
308
  subject(:type) { Attributor::Hash.of(key: key_type, value: value_type) }
294
309
 
295
310
  it { should be_a(::Class) }
296
311
  its(:ancestors) { should include(Attributor::Hash) }
297
- its(:key_type) { should == Attributor::String }
298
- its(:value_type) { should == Attributor::Integer }
312
+ its(:key_type) { should eq Attributor::String }
313
+ its(:value_type) { should eq Attributor::Integer }
299
314
 
300
315
  context '.load' do
301
- let(:value) { {one: '2', 3 => 4} }
316
+ let(:value) { { one: '2', 3 => 4 } }
302
317
 
303
318
  subject(:hash) { type.load(value) }
304
319
 
305
320
  it 'coerces the types properly' do
306
- hash['one'].should eq(2)
307
- hash['3'].should eq(4)
321
+ expect(hash['one']).to eq(2)
322
+ expect(hash['3']).to eq(4)
308
323
  end
309
-
310
324
  end
311
-
312
325
  end
313
-
314
326
  end
315
327
 
316
328
  context '.construct' do
@@ -323,36 +335,35 @@ describe Attributor::Hash do
323
335
  end
324
336
  end
325
337
 
326
-
327
338
  subject(:type) { Attributor::Hash.construct(block) }
328
339
 
329
- it { should_not be(Attributor::Hash)
330
- }
340
+ it do
341
+ should_not be(Attributor::Hash)
342
+ end
331
343
 
332
344
  context 'loading' do
333
- let(:date) { DateTime.parse("2014-07-15") }
345
+ let(:date) { DateTime.parse('2014-07-15') }
334
346
  let(:value) do
335
- {'a string' => 12, '1' => '2', :some_date => date.to_s}
347
+ { 'a string' => 12, '1' => '2', :some_date => date.to_s }
336
348
  end
337
349
 
338
- subject(:hash) { type.load(value)}
350
+ subject(:hash) { type.load(value) }
339
351
 
340
352
  it 'loads' do
341
- hash['a string'].should eq('12')
342
- hash['1'].should eq(2)
343
- hash[:some_date].should eq(date)
344
- hash['defaulted'].should eq('default value')
353
+ expect(hash['a string']).to eq('12')
354
+ expect(hash['1']).to eq(2)
355
+ expect(hash[:some_date]).to eq(date)
356
+ expect(hash['defaulted']).to eq('default value')
345
357
  end
346
358
 
347
359
  context 'with unknown keys in input' do
348
360
  it 'raises an error' do
349
- expect {
350
- type.load({'other_key' => :value})
351
- }.to raise_error(Attributor::AttributorException)
361
+ expect do
362
+ type.load('other_key' => :value)
363
+ end.to raise_error(Attributor::AttributorException)
352
364
  end
353
365
  end
354
366
 
355
-
356
367
  context 'with a key_type' do
357
368
  let(:block) do
358
369
  proc do
@@ -365,16 +376,15 @@ describe Attributor::Hash do
365
376
 
366
377
  subject(:type) { Attributor::Hash.of(key: String).construct(block) }
367
378
  let(:value) do
368
- {'a string' => 12, 1 => '2', :some_date => date.to_s}
379
+ { 'a string' => 12, 1 => '2', :some_date => date.to_s }
369
380
  end
370
381
 
371
382
  it 'loads' do
372
- hash['a string'].should eq('12')
373
- hash['1'].should eq(2)
374
- hash['some_date'].should eq(date)
375
- hash['defaulted'].should eq('default value')
383
+ expect(hash['a string']).to eq('12')
384
+ expect(hash['1']).to eq(2)
385
+ expect(hash['some_date']).to eq(date)
386
+ expect(hash['defaulted']).to eq('default value')
376
387
  end
377
-
378
388
  end
379
389
  end
380
390
 
@@ -386,75 +396,73 @@ describe Attributor::Hash do
386
396
  end
387
397
 
388
398
  it 'raises an error' do
389
- expect {
390
- Attributor::Hash.of(key:String).construct(block).keys
391
- }.to raise_error(/Invalid key: :some_date, must be instance of String/)
399
+ expect do
400
+ Attributor::Hash.of(key: String).construct(block).keys
401
+ end.to raise_error(/Invalid key: :some_date, must be instance of String/)
392
402
  end
393
-
394
403
  end
395
404
  end
396
405
 
397
406
  context '.check_option!' do
398
407
  context ':case_insensitive_load' do
399
-
400
408
  it 'is valid when key_type is a string' do
401
- Attributor::Hash.of(key:String).check_option!(:case_insensitive_load, true).should == :ok
409
+ expect(Attributor::Hash.of(key: String).check_option!(:case_insensitive_load, true)).to eq :ok
402
410
  end
403
411
 
404
412
  it 'is invalid when key_type is non-string' do
405
- expect {
406
- Attributor::Hash.of(key:Integer).check_option!(:case_insensitive_load, true)
407
- }.to raise_error(Attributor::AttributorException, /:case_insensitive_load may not be used/)
413
+ expect do
414
+ Attributor::Hash.of(key: Integer).check_option!(:case_insensitive_load, true)
415
+ end.to raise_error(Attributor::AttributorException,
416
+ /:case_insensitive_load may not be used/)
408
417
  end
409
-
410
418
  end
411
- it 'rejects unknown options' do
412
- subject.check_option!(:bad_option, Object).should == :unknown
419
+ it 'rejects unknown options' do
420
+ expect(subject.check_option!(:bad_option, Object)).to eq :unknown
413
421
  end
414
-
415
422
  end
416
423
 
417
424
  context '.add_requirement' do
418
- let(:req_type){ :all }
419
- let(:req){ double("requirement", type: req_type, attr_names: req_attributes)}
425
+ let(:req_type) { :all }
426
+ let(:req) { double('requirement', type: req_type, attr_names: req_attributes) }
420
427
  context 'with valid attributes' do
421
- let(:req_attributes){ [:name] }
428
+ let(:req_attributes) { [:name] }
422
429
  it 'successfully saves it in the class' do
423
430
  HashWithStrings.add_requirement(req)
424
- HashWithStrings.requirements.should include(req)
431
+ expect(HashWithStrings.requirements).to include(req)
425
432
  end
426
433
  end
427
434
  context 'with attributes not defined in the class' do
428
- let(:req_attributes){ [:name, :invalid, :notgood] }
435
+ let(:req_attributes) { [:name, :invalid, :notgood] }
429
436
  it 'it complains loudly' do
430
- expect{
437
+ expect do
431
438
  HashWithStrings.add_requirement(req)
432
- }.to raise_error("Invalid attribute name(s) found (invalid, notgood) when defining a requirement of type all for HashWithStrings .The only existing attributes are [:name, :something]")
439
+ end.to raise_error(
440
+ 'Invalid attribute name(s) found (invalid, notgood) when defining a requirement of type all for HashWithStrings .The only existing attributes are [:name, :something]'
441
+ )
433
442
  end
434
443
  end
435
444
  end
436
445
 
437
446
  context '.dump' do
438
-
439
- let(:value) { {one: 1, two: 2} }
447
+ let(:value) { { one: 1, two: 2 } }
440
448
  let(:opts) { {} }
441
449
 
442
450
  it 'it is Dumpable' do
443
- type.new.is_a?(Attributor::Dumpable).should be(true)
451
+ expect(type.new.is_a?(Attributor::Dumpable)).to be(true)
444
452
  end
445
453
 
446
454
  context 'for a simple (untyped) hash' do
447
455
  it 'returns the untouched hash value' do
448
- type.dump(value, opts).should eq(value)
456
+ expect(type.dump(value, opts)).to eq(value)
449
457
  end
450
458
  end
451
459
 
452
460
  context 'for a typed hash' do
453
461
  before do
454
- subtype.should_receive(:dump).exactly(2).times.and_call_original
462
+ expect(subtype).to receive(:dump).exactly(2).times.and_call_original
455
463
  end
456
- let(:value1) { {first: "Joe", last: "Moe"} }
457
- let(:value2) { {first: "Mary", last: "Foe"} }
464
+ let(:value1) { { first: 'Joe', last: 'Moe' } }
465
+ let(:value2) { { first: 'Mary', last: 'Foe' } }
458
466
  let(:value) { { id1: subtype.new(value1), id2: subtype.new(value2) } }
459
467
  let(:subtype) do
460
468
  Class.new(Attributor::Model) do
@@ -468,11 +476,11 @@ describe Attributor::Hash do
468
476
 
469
477
  it 'returns a hash with the dumped values and keys' do
470
478
  dumped_value = type.dump(value, opts)
471
- dumped_value.should be_kind_of(::Hash)
472
- dumped_value.keys.should =~ ['id1','id2']
473
- dumped_value.values.should have(2).items
474
- dumped_value['id1'].should == value1
475
- dumped_value['id2'].should == value2
479
+ expect(dumped_value).to be_kind_of(::Hash)
480
+ expect(dumped_value.keys).to match_array %w(id1 id2)
481
+ expect(dumped_value.values).to have(2).items
482
+ expect(dumped_value['id1']).to eq value1
483
+ expect(dumped_value['id2']).to eq value2
476
484
  end
477
485
 
478
486
  context 'that has nil attribute values' do
@@ -480,31 +488,29 @@ describe Attributor::Hash do
480
488
 
481
489
  it 'correctly returns nil rather than trying to dump their contents' do
482
490
  dumped_value = type.dump(value, opts)
483
- dumped_value.should be_kind_of(::Hash)
484
- dumped_value.keys.should =~ ['id1','id2']
485
- dumped_value['id1'].should == nil
486
- dumped_value['id2'].should == value2
491
+ expect(dumped_value).to be_kind_of(::Hash)
492
+ expect(dumped_value.keys).to match_array %w(id1 id2)
493
+ expect(dumped_value['id1']).to be nil
494
+ expect(dumped_value['id2']).to eq value2
487
495
  end
488
496
  end
489
497
  end
490
-
491
498
  end
492
499
 
493
500
  context '#validate' do
494
501
  context 'for a key and value typed hash' do
495
- let(:key_type){ Integer }
496
- let(:value_type){ DateTime }
502
+ let(:key_type) { Integer }
503
+ let(:value_type) { DateTime }
497
504
 
498
505
  let(:type) { Attributor::Hash.of(key: key_type, value: value_type) }
499
506
  subject(:hash) { type.new('one' => :two) }
500
507
 
501
508
  it 'returns errors for key and value' do
502
509
  errors = hash.validate
503
- errors.should have(2).items
504
-
505
- errors.should include("Attribute $.key(\"one\") received value: \"one\" is of the wrong type (got: String, expected: Attributor::Integer)")
506
- errors.should include("Attribute $.value(:two) received value: :two is of the wrong type (got: Symbol, expected: Attributor::DateTime)")
510
+ expect(errors).to have(2).items
507
511
 
512
+ expect(errors).to include('Attribute $.key("one") received value: "one" is of the wrong type (got: String, expected: Attributor::Integer)')
513
+ expect(errors).to include('Attribute $.value(:two) received value: :two is of the wrong type (got: Symbol, expected: Attributor::DateTime)')
508
514
  end
509
515
  end
510
516
 
@@ -519,18 +525,16 @@ describe Attributor::Hash do
519
525
 
520
526
  let(:type) { Attributor::Hash.construct(block) }
521
527
 
522
- let(:values) { {'integer' => 'one', 'datetime' => 'now' } }
528
+ let(:values) { { 'integer' => 'one', 'datetime' => 'now' } }
523
529
  subject(:hash) { type.new(values) }
524
530
 
525
531
  it 'validates the keys' do
526
532
  errors = hash.validate
527
- errors.should have(3).items
528
- errors.should include("Attribute $.key(\"not-optional\") is required")
533
+ expect(errors).to have(3).items
534
+ expect(errors).to include('Attribute $.key("not-optional") is required')
529
535
  end
530
-
531
536
  end
532
537
 
533
-
534
538
  context 'with requirements defined' do
535
539
  let(:type) { Attributor::Hash.construct(block) }
536
540
 
@@ -548,9 +552,9 @@ describe Attributor::Hash do
548
552
 
549
553
  it 'complains not all the listed elements are set (false or true)' do
550
554
  errors = type.new('name' => 'CAP').validate
551
- errors.should have(2).items
552
- ['consistency','availability'].each do |name|
553
- errors.should include("Key #{name} is required for $.")
555
+ expect(errors).to have(2).items
556
+ %w(consistency availability).each do |name|
557
+ expect(errors).to include("Key #{name} is required for $.")
554
558
  end
555
559
  end
556
560
  end
@@ -568,9 +572,9 @@ describe Attributor::Hash do
568
572
 
569
573
  it 'complains if less than 2 in the group are set (false or true)' do
570
574
  errors = type.new('name' => 'CAP', 'consistency' => false).validate
571
- errors.should have(1).items
572
- errors.should include(
573
- "At least 2 keys out of [\"consistency\", \"availability\", \"partitioning\"] are required to be passed in for $. Found [\"consistency\"]"
575
+ expect(errors).to have(1).items
576
+ expect(errors).to include(
577
+ 'At least 2 keys out of ["consistency", "availability", "partitioning"] are required to be passed in for $. Found ["consistency"]'
574
578
  )
575
579
  end
576
580
  end
@@ -588,8 +592,8 @@ describe Attributor::Hash do
588
592
 
589
593
  it 'complains if more than 2 in the group are set (false or true)' do
590
594
  errors = type.new('name' => 'CAP', 'consistency' => false, 'availability' => true, 'partitioning' => false).validate
591
- errors.should have(1).items
592
- errors.should include("At most 2 keys out of [\"consistency\", \"availability\", \"partitioning\"] can be passed in for $. Found [\"consistency\", \"availability\", \"partitioning\"]")
595
+ expect(errors).to have(1).items
596
+ expect(errors).to include('At most 2 keys out of ["consistency", "availability", "partitioning"] can be passed in for $. Found ["consistency", "availability", "partitioning"]')
593
597
  end
594
598
  end
595
599
 
@@ -606,13 +610,13 @@ describe Attributor::Hash do
606
610
 
607
611
  it 'complains if less than 1 in the group are set (false or true)' do
608
612
  errors = type.new('name' => 'CAP').validate
609
- errors.should have(1).items
610
- errors.should include("Exactly 1 of the following keys [\"consistency\", \"availability\", \"partitioning\"] are required for $. Found 0 instead: []")
613
+ expect(errors).to have(1).items
614
+ expect(errors).to include('Exactly 1 of the following keys ["consistency", "availability", "partitioning"] are required for $. Found 0 instead: []')
611
615
  end
612
616
  it 'complains if more than 1 in the group are set (false or true)' do
613
617
  errors = type.new('name' => 'CAP', 'consistency' => false, 'availability' => true).validate
614
- errors.should have(1).items
615
- errors.should include("Exactly 1 of the following keys [\"consistency\", \"availability\", \"partitioning\"] are required for $. Found 2 instead: [\"consistency\", \"availability\"]")
618
+ expect(errors).to have(1).items
619
+ expect(errors).to include('Exactly 1 of the following keys ["consistency", "availability", "partitioning"] are required for $. Found 2 instead: ["consistency", "availability"]')
616
620
  end
617
621
  end
618
622
 
@@ -629,8 +633,8 @@ describe Attributor::Hash do
629
633
 
630
634
  it 'complains if two or more in the group are set (false or true)' do
631
635
  errors = type.new('name' => 'CAP', 'consistency' => false, 'availability' => true).validate
632
- errors.should have(1).items
633
- errors.should include("keys [\"consistency\", \"availability\"] are mutually exclusive for $.")
636
+ expect(errors).to have(1).items
637
+ expect(errors).to include('keys ["consistency", "availability"] are mutually exclusive for $.')
634
638
  end
635
639
  end
636
640
 
@@ -653,38 +657,36 @@ describe Attributor::Hash do
653
657
 
654
658
  it 'complains not all the listed elements are set (false or true)' do
655
659
  errors = type.new('name' => 'CAP').validate
656
- errors.should have(1).items
657
- errors.should include(
658
- "At least 1 keys out of [\"consistency\", \"availability\", \"partitioning\"] are required to be passed in for $. Found none"
660
+ expect(errors).to have(1).items
661
+ expect(errors).to include(
662
+ 'At least 1 keys out of ["consistency", "availability", "partitioning"] are required to be passed in for $. Found none'
659
663
  )
660
664
  end
661
665
  end
662
666
  end
663
-
664
667
  end
665
668
 
666
669
  context 'in an Attribute' do
667
670
  let(:options) { {} }
668
- subject(:attribute) { Attributor::Attribute.new(Attributor::Hash, options)}
671
+ subject(:attribute) { Attributor::Attribute.new(Attributor::Hash, options) }
669
672
 
670
673
  context 'with an example option that is a proc' do
671
- let(:example_hash) { {:key => "value"} }
674
+ let(:example_hash) { { key: 'value' } }
672
675
  let(:options) { { example: proc { example_hash } } }
673
676
  it 'uses the hash' do
674
- attribute.example.should eq(example_hash)
677
+ expect(attribute.example).to eq(example_hash)
675
678
  end
676
679
  end
677
-
678
680
  end
679
681
 
680
682
  context '.describe' do
681
- let(:example){ nil }
683
+ let(:example) { nil }
682
684
  subject(:description) { type.describe(example: example) }
683
685
  context 'for hashes with key and value types' do
684
686
  it 'describes the type correctly' do
685
- description[:name].should eq('Hash')
686
- description[:key].should eq(type:{name: 'Object', id: 'Attributor-Object', family: 'any'})
687
- description[:value].should eq(type:{name: 'Object', id: 'Attributor-Object', family: 'any'})
687
+ expect(description[:name]).to eq('Hash')
688
+ expect(description[:key]).to eq(type: { name: 'Object', id: 'Attributor-Object', family: 'any' })
689
+ expect(description[:value]).to eq(type: { name: 'Object', id: 'Attributor-Object', family: 'any' })
688
690
  end
689
691
  end
690
692
 
@@ -696,7 +698,7 @@ describe Attributor::Hash do
696
698
  key 'some_date', DateTime
697
699
  key 'defaulted', String, default: 'default value'
698
700
  requires do
699
- all.of '1','some_date'
701
+ all.of '1', 'some_date'
700
702
  exclusive 'some_date', 'defaulted'
701
703
  at_least(1).of 'a string', 'some_date'
702
704
  at_most(2).of 'a string', 'some_date'
@@ -708,30 +710,29 @@ describe Attributor::Hash do
708
710
  let(:type) { Attributor::Hash.of(key: String).construct(block) }
709
711
 
710
712
  it 'describes the type correctly' do
711
- description[:name].should eq('Hash')
712
- description[:key].should eq(type:{name: 'String', id: 'Attributor-String', family: 'string'})
713
- description.should_not have_key(:value)
713
+ expect(description[:name]).to eq('Hash')
714
+ expect(description[:key]).to eq(type: { name: 'String', id: 'Attributor-String', family: 'string' })
715
+ expect(description).not_to have_key(:value)
714
716
  end
715
717
 
716
718
  it 'describes the type attributes correctly' do
717
719
  attrs = description[:attributes]
718
720
 
719
- attrs['a string'].should eq(type: {name: 'String', id: 'Attributor-String', family: 'string'} )
720
- attrs['1'].should eq(type: {name: 'Integer', id: 'Attributor-Integer', family: 'numeric'}, options: {min: 1, max: 20} )
721
- attrs['some_date'].should eq(type: {name: 'DateTime', id: 'Attributor-DateTime', family: 'temporal'})
722
- attrs['defaulted'].should eq(type: {name: 'String', id: 'Attributor-String', family: 'string'}, default: 'default value')
721
+ expect(attrs['a string']).to eq(type: { name: 'String', id: 'Attributor-String', family: 'string' })
722
+ expect(attrs['1']).to eq(type: { name: 'Integer', id: 'Attributor-Integer', family: 'numeric' }, options: { min: 1, max: 20 })
723
+ expect(attrs['some_date']).to eq(type: { name: 'DateTime', id: 'Attributor-DateTime', family: 'temporal' })
724
+ expect(attrs['defaulted']).to eq(type: { name: 'String', id: 'Attributor-String', family: 'string' }, default: 'default value')
723
725
  end
724
726
 
725
727
  it 'describes the type requirements correctly' do
726
-
727
728
  reqs = description[:requirements]
728
- reqs.should be_kind_of(Array)
729
- reqs.size.should be(5)
730
- reqs.should include( type: :all, attributes: ['1','some_date'] )
731
- reqs.should include( type: :exclusive, attributes: ['some_date','defaulted'] )
732
- reqs.should include( type: :at_least, attributes: ['a string','some_date'], count: 1 )
733
- reqs.should include( type: :at_most, attributes: ['a string','some_date'], count: 2 )
734
- reqs.should include( type: :exactly, attributes: ['a string','some_date'], count: 1 )
729
+ expect(reqs).to be_kind_of(Array)
730
+ expect(reqs.size).to be(5)
731
+ expect(reqs).to include(type: :all, attributes: %w(1 some_date))
732
+ expect(reqs).to include(type: :exclusive, attributes: %w(some_date defaulted))
733
+ expect(reqs).to include(type: :at_least, attributes: ['a string', 'some_date'], count: 1)
734
+ expect(reqs).to include(type: :at_most, attributes: ['a string', 'some_date'], count: 2)
735
+ expect(reqs).to include(type: :exactly, attributes: ['a string', 'some_date'], count: 1)
735
736
  end
736
737
 
737
738
  context 'merging requires.all with attribute required: true' do
@@ -746,8 +747,8 @@ describe Attributor::Hash do
746
747
  end
747
748
  end
748
749
  it 'includes attributes with required: true into the :all requirements' do
749
- req_all = description[:requirements].select{|r| r[:type] == :all}.first
750
- req_all[:attributes].should include( 'required string','some_date' )
750
+ req_all = description[:requirements].select { |r| r[:type] == :all }.first
751
+ expect(req_all[:attributes]).to include('required string', 'some_date')
751
752
  end
752
753
  end
753
754
 
@@ -759,21 +760,21 @@ describe Attributor::Hash do
759
760
  end
760
761
  end
761
762
  it 'includes attributes with required: true into the :all requirements' do
762
- req_all = description[:requirements].select{|r| r[:type] == :all}.first
763
- req_all.should_not be(nil)
764
- req_all[:attributes].should include( 'required string','required integer' )
763
+ req_all = description[:requirements].select { |r| r[:type] == :all }.first
764
+ expect(req_all).not_to be(nil)
765
+ expect(req_all[:attributes]).to include('required string', 'required integer')
765
766
  end
766
767
  end
767
768
 
768
769
  context 'with an example' do
769
- let(:example){ type.example }
770
+ let(:example) { type.example }
770
771
 
771
772
  it 'should have the matching example for each leaf key' do
772
- description[:attributes].keys.should =~ type.keys.keys
773
- description[:attributes].each do |name,sub_description|
774
- sub_description.should have_key(:example)
773
+ expect(description[:attributes].keys).to match_array type.keys.keys
774
+ description[:attributes].each do |name, sub_description|
775
+ expect(sub_description).to have_key(:example)
775
776
  val = type.attributes[name].dump(example[name])
776
- sub_description[:example].should eq val
777
+ expect(sub_description[:example]).to eq val
777
778
  end
778
779
  end
779
780
  end
@@ -781,17 +782,17 @@ describe Attributor::Hash do
781
782
  end
782
783
 
783
784
  context '#dump' do
784
- let(:key_type){ String }
785
- let(:value_type){ Integer }
786
- let(:hash) { {one: '2', 3 => 4} }
785
+ let(:key_type) { String }
786
+ let(:value_type) { Integer }
787
+ let(:hash) { { one: '2', 3 => 4 } }
787
788
  let(:type) { Attributor::Hash.of(key: key_type, value: value_type) }
788
789
  let(:value) { type.load(hash) }
789
790
 
790
791
  subject(:output) { value.dump }
791
792
 
792
793
  it 'dumps the contents properly' do
793
- output.should be_kind_of(::Hash)
794
- output.should eq('one' => 2, '3' => 4)
794
+ expect(output).to be_kind_of(::Hash)
795
+ expect(output).to eq('one' => 2, '3' => 4)
795
796
  end
796
797
 
797
798
  context 'with a model as value type' do
@@ -803,17 +804,16 @@ describe Attributor::Hash do
803
804
  end
804
805
  end
805
806
  end
806
- let(:hash) { {one: value_type.example} }
807
-
807
+ let(:hash) { { one: value_type.example } }
808
808
  end
809
809
  context 'will always return a top level hash' do
810
- subject(:type_dump){ type.dump(value) }
811
- let(:key_type){ Attributor::Object }
812
- let(:value_type){ Attributor::Object }
810
+ subject(:type_dump) { type.dump(value) }
811
+ let(:key_type) { Attributor::Object }
812
+ let(:value_type) { Attributor::Object }
813
813
 
814
814
  it 'even when key/types are object' do
815
- subject.should be_kind_of(::Hash)
816
- subject.should eq( hash )
815
+ expect(subject).to be_kind_of(::Hash)
816
+ expect(subject).to eq(hash)
817
817
  end
818
818
  end
819
819
 
@@ -827,13 +827,13 @@ describe Attributor::Hash do
827
827
  end
828
828
  end
829
829
 
830
- let(:chicken) { {'name' => 'bob'} }
830
+ let(:chicken) { { 'name' => 'bob' } }
831
831
 
832
- let(:value) { {'id' => '1', 'chicken' => chicken } }
833
- let(:expected) { {'id' => 1, 'chicken' => Chicken.dump(chicken) } }
832
+ let(:value) { { 'id' => '1', 'chicken' => chicken } }
833
+ let(:expected) { { 'id' => 1, 'chicken' => Chicken.dump(chicken) } }
834
834
 
835
835
  it 'properly dumps the values' do
836
- type.dump(value).should eq(expected)
836
+ expect(type.dump(value)).to eq(expected)
837
837
  end
838
838
 
839
839
  context 'with allow_extra: true' do
@@ -846,10 +846,10 @@ describe Attributor::Hash do
846
846
  end
847
847
  end
848
848
 
849
- let(:value) { {'id' => '1', 'chicken' => chicken, 'rank' => 'bob rank'} }
850
- let(:expected) { {'id' => 1, 'chicken' => Chicken.dump(chicken), 'rank' => 'bob rank' } }
849
+ let(:value) { { 'id' => '1', 'chicken' => chicken, 'rank' => 'bob rank' } }
850
+ let(:expected) { { 'id' => 1, 'chicken' => Chicken.dump(chicken), 'rank' => 'bob rank' } }
851
851
  it 'preserves the extra keys at the top level' do
852
- type.dump(value).should eq(expected)
852
+ expect(type.dump(value)).to eq(expected)
853
853
  end
854
854
 
855
855
  context 'with extra option' do
@@ -863,9 +863,9 @@ describe Attributor::Hash do
863
863
  end
864
864
  end
865
865
 
866
- let(:expected) { {'id' => 1, 'chicken' => Chicken.dump(chicken), 'other' => {'rank' => 'bob rank' }} }
866
+ let(:expected) { { 'id' => 1, 'chicken' => Chicken.dump(chicken), 'other' => { 'rank' => 'bob rank' } } }
867
867
  it 'dumps the extra keys inside the subhash' do
868
- type.dump(value).should eq(expected)
868
+ expect(type.dump(value)).to eq(expected)
869
869
  end
870
870
  end
871
871
  end
@@ -873,7 +873,6 @@ describe Attributor::Hash do
873
873
  end
874
874
 
875
875
  context '.from_hash' do
876
-
877
876
  context 'without allowing extra keys' do
878
877
  let(:type) do
879
878
  Class.new(Attributor::Hash) do
@@ -885,29 +884,29 @@ describe Attributor::Hash do
885
884
  end
886
885
  end
887
886
  end
888
- subject(:input){ {} }
887
+ subject(:input) { {} }
889
888
  subject(:output) { type.load(input) }
890
889
 
891
- its(:class){ should be(type) }
890
+ its(:class) { should be(type) }
892
891
 
893
- let(:load_context) { "$.some_root" }
892
+ let(:load_context) { '$.some_root' }
894
893
  it 'complains about the extra, with the right context' do
895
- expect{
896
- type.load( {one: 'one', three: 3} , load_context )
897
- }.to raise_error(Attributor::AttributorException,/Unknown key received: :three while loading \$\.some_root.key\(:three\)/)
894
+ expect do
895
+ type.load({ one: 'one', three: 3 }, load_context)
896
+ end.to raise_error(Attributor::AttributorException, /Unknown key received: :three while loading \$\.some_root.key\(:three\)/)
898
897
  end
899
898
  context 'properly sets them (and loads them) in the created instance' do
900
- let(:input){ {one: 'one', two: 2 } }
899
+ let(:input) { { one: 'one', two: 2 } }
901
900
 
902
- its(:keys){ should eq([:one, :two])}
903
- its([:one]){ should eq('one') }
904
- its([:two]){ should eq('2') } #loaded as a string
901
+ its(:keys) { should eq([:one, :two]) }
902
+ its([:one]) { should eq('one') }
903
+ its([:two]) { should eq('2') } # loaded as a string
905
904
  end
906
905
  context 'properly sets the default values when not passed in' do
907
- let(:input){ {one: 'one'} }
906
+ let(:input) { { one: 'one' } }
908
907
 
909
- its([:one]){ should eq('one') }
910
- its([:two]){ should eq('two') }
908
+ its([:one]) { should eq('one') }
909
+ its([:two]) { should eq('two') }
911
910
  end
912
911
  end
913
912
 
@@ -920,10 +919,10 @@ describe Attributor::Hash do
920
919
  end
921
920
  end
922
921
  end
923
- let(:input){ {one: 'one', three: 'tres' } }
922
+ let(:input) { { one: 'one', three: 'tres' } }
924
923
  subject(:output) { type.load(input) }
925
924
 
926
- its(:keys){ should eq([:one,:three])}
925
+ its(:keys) { should eq([:one, :three]) }
927
926
  end
928
927
  context 'inside an :other subkey' do
929
928
  let(:type) do
@@ -934,12 +933,12 @@ describe Attributor::Hash do
934
933
  end
935
934
  end
936
935
  end
937
- let(:input){ {one: 'one', three: 'tres' } }
936
+ let(:input) { { one: 'one', three: 'tres' } }
938
937
  subject(:output) { type.load(input) }
939
938
 
940
- its(:keys){ should =~ [:one,:other] }
939
+ its(:keys) { should match_array [:one, :other] }
941
940
  it 'has the key inside the :other hash' do
942
- expect(output[:other]).to eq({three: 'tres'})
941
+ expect(output[:other]).to eq(three: 'tres')
943
942
  end
944
943
  end
945
944
  end
@@ -955,20 +954,19 @@ describe Attributor::Hash do
955
954
  key 'CamelCase', Integer
956
955
  end
957
956
  end
958
- let(:input) { {'DOWNCASE' => 1, 'upcase' => 2, 'CamelCase' => 3} }
957
+ let(:input) { { 'DOWNCASE' => 1, 'upcase' => 2, 'CamelCase' => 3 } }
959
958
  subject(:output) { type.load(input) }
960
959
 
961
960
  context 'when defined' do
962
-
963
961
  it 'maps the incoming keys to defined keys, regardless of case' do
964
- output['downcase'].should eq(1)
965
- output['UPCASE'].should eq(2)
966
- output['CamelCase'].should eq(3)
962
+ expect(output['downcase']).to eq(1)
963
+ expect(output['UPCASE']).to eq(2)
964
+ expect(output['CamelCase']).to eq(3)
967
965
  end
968
966
  it 'has loaded the (internal) insensitive_map upon building the definition' do
969
967
  type.definition
970
- type.insensitive_map.should be_kind_of(::Hash)
971
- type.insensitive_map.keys.should =~ ["downcase","upcase","camelcase"]
968
+ expect(type.insensitive_map).to be_kind_of(::Hash)
969
+ expect(type.insensitive_map.keys).to match_array %w(downcase upcase camelcase)
972
970
  end
973
971
  end
974
972
 
@@ -977,7 +975,7 @@ describe Attributor::Hash do
977
975
 
978
976
  it 'skips the loading of the (internal) insensitive_map' do
979
977
  type.definition
980
- type.insensitive_map.should be_nil
978
+ expect(type.insensitive_map).to be_nil
981
979
  end
982
980
  end
983
981
  end
@@ -994,19 +992,19 @@ describe Attributor::Hash do
994
992
  end
995
993
  end
996
994
 
997
- let(:input) { {one: 'one', three: 3} }
995
+ let(:input) { { one: 'one', three: 3 } }
998
996
  subject(:output) { type.load(input) }
999
997
 
1000
998
  context 'that should be saved at the top level' do
1001
- its(:keys) { should =~ [:one, :two, :three] }
999
+ its(:keys) { should match_array [:one, :two, :three] }
1002
1000
 
1003
1001
  it 'loads the extra keys' do
1004
- output[:one].should eq('one')
1005
- output[:two].should eq('two')
1006
- output[:three].should eq('3')
1002
+ expect(output[:one]).to eq('one')
1003
+ expect(output[:two]).to eq('two')
1004
+ expect(output[:three]).to eq('3')
1007
1005
  end
1008
1006
 
1009
- its( :validate ){ should be_empty }
1007
+ its(:validate) { should be_empty }
1010
1008
  end
1011
1009
 
1012
1010
  context 'that should be grouped into a sub-hash' do
@@ -1016,25 +1014,24 @@ describe Attributor::Hash do
1016
1014
  end
1017
1015
  end
1018
1016
 
1019
- its(:keys) { should =~ [:one, :two, :options] }
1017
+ its(:keys) { should match_array [:one, :two, :options] }
1020
1018
  it 'loads the extra keys into :options sub-hash' do
1021
- output[:one].should eq('one')
1022
- output[:two].should eq('two')
1023
- output[:options].should eq({three: 3})
1019
+ expect(output[:one]).to eq('one')
1020
+ expect(output[:two]).to eq('two')
1021
+ expect(output[:options]).to eq(three: 3)
1024
1022
  end
1025
- its( :validate ){ should be_empty }
1023
+ its(:validate) { should be_empty }
1026
1024
 
1027
1025
  context 'with an options value already provided' do
1028
- its(:keys) { should =~ [:one, :two, :options] }
1029
- let(:input) { {one: 'one', three: 3, options: {four: 4}} }
1026
+ its(:keys) { should match_array [:one, :two, :options] }
1027
+ let(:input) { { one: 'one', three: 3, options: { four: 4 } } }
1030
1028
 
1031
1029
  it 'loads the extra keys into :options sub-hash' do
1032
- output[:one].should eq('one')
1033
- output[:two].should eq('two')
1034
- output[:options].should eq({three: 3, four: 4})
1030
+ expect(output[:one]).to eq('one')
1031
+ expect(output[:two]).to eq('two')
1032
+ expect(output[:options]).to eq(three: 3, four: 4)
1035
1033
  end
1036
- its( :validate ){ should be_empty }
1037
-
1034
+ its(:validate) { should be_empty }
1038
1035
  end
1039
1036
  end
1040
1037
 
@@ -1049,53 +1046,50 @@ describe Attributor::Hash do
1049
1046
  end
1050
1047
  end
1051
1048
 
1052
- let(:chicken) { {name: 'bob'} }
1049
+ let(:chicken) { { name: 'bob' } }
1053
1050
  subject(:hash) { type.new }
1054
1051
 
1055
1052
  context '#set' do
1056
1053
  it 'sets values into "extra" keys if appplicable' do
1057
- hash.should_not have_key('others')
1054
+ expect(hash).not_to have_key('others')
1058
1055
  hash.set 'foo', 'bar'
1059
- hash['others'].should have_key('foo')
1060
- hash.should have_key('others')
1061
- hash['others']['foo'].should eq('bar')
1056
+ expect(hash['others']).to have_key('foo')
1057
+ expect(hash).to have_key('others')
1058
+ expect(hash['others']['foo']).to eq('bar')
1062
1059
  end
1063
1060
 
1064
1061
  it 'loads values before saving into the contents' do
1065
1062
  hash.set 'chicken', chicken
1066
- hash['chicken'].should be_a(Chicken)
1063
+ expect(hash['chicken']).to be_a(Chicken)
1067
1064
  end
1068
1065
  end
1069
1066
 
1070
1067
  context '#get' do
1071
1068
  before do
1072
1069
  hash['chicken'] = chicken
1073
- hash['chicken'].should eq(chicken)
1070
+ expect(hash['chicken']).to eq(chicken)
1074
1071
  end
1075
1072
 
1076
1073
  it 'loads and updates the saved value' do
1077
- hash.get('chicken').should be_a(Chicken)
1078
- hash['chicken'].should be_a(Chicken)
1074
+ expect(hash.get('chicken')).to be_a(Chicken)
1075
+ expect(hash['chicken']).to be_a(Chicken)
1079
1076
  end
1080
1077
 
1081
1078
  it 'retrieves values from an "extra" key' do
1082
1079
  bar = double('bar')
1083
1080
  hash.set 'foo', bar
1084
- hash.get('others').get('foo').should be(bar)
1081
+ expect(hash.get('others').get('foo')).to be(bar)
1085
1082
 
1086
- hash.get('foo').should be(bar)
1083
+ expect(hash.get('foo')).to be(bar)
1087
1084
  end
1088
1085
 
1089
1086
  it 'does not set a key that is unset' do
1090
- hash.should_not have_key('id')
1091
- hash.get('id').should be(nil)
1092
- hash.should_not have_key('id')
1087
+ expect(hash).not_to have_key('id')
1088
+ expect(hash.get('id')).to be(nil)
1089
+ expect(hash).not_to have_key('id')
1093
1090
  end
1094
-
1095
1091
  end
1096
-
1097
1092
  end
1098
-
1099
1093
  end
1100
1094
 
1101
1095
  context '#merge' do
@@ -1120,6 +1114,8 @@ describe Attributor::Hash do
1120
1114
  it 'merges' do
1121
1115
  expect(merger.merge(good_mergee)).to eq(result)
1122
1116
  end
1117
+ end
1123
1118
 
1119
+ context Attributor::InvalidDefinition do
1124
1120
  end
1125
1121
  end