hashme 0.1.2 → 0.2.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.
@@ -11,10 +11,10 @@ describe Hashme do
11
11
 
12
12
  describe '.build' do
13
13
  it "should create a Model and give a block to build it" do
14
- @model.should_receive(:call_in_block)
14
+ expect(@model).to receive(:call_in_block)
15
15
  @model.build do |model|
16
16
  @model.call_in_block
17
- model.should be_kind_of(@model)
17
+ expect(model).to be_kind_of(@model)
18
18
  end
19
19
  end
20
20
  end
@@ -29,16 +29,15 @@ describe Hashme do
29
29
 
30
30
  it "should accept and set attributes" do
31
31
  @obj = @model.new(:name => "Sam")
32
- @obj.name.should eql("Sam")
32
+ expect(@obj.name).to eql("Sam")
33
33
  end
34
34
 
35
35
  it "should set default values so they are accessible by hash" do
36
36
  @model.property :surname, String, :default => "Nowl"
37
37
  @obj = @model.new
38
- @obj.to_hash[:surname].should eql('Nowl')
38
+ expect(@obj.to_hash[:surname]).to eql('Nowl')
39
39
  end
40
40
 
41
-
42
41
  end
43
42
 
44
43
  end
@@ -14,41 +14,44 @@ describe Hashme::CastedArray do
14
14
  end
15
15
 
16
16
  describe "#initialize" do
17
+ let :property do
18
+ Hashme::Property.new(:name, String)
19
+ end
17
20
  before :each do
18
- @prop = Hashme::Property.new(:name, String)
19
- @obj = Hashme::CastedArray.new(owner, @prop, ['test'])
21
+ @obj = Hashme::CastedArray.new(property, owner, ['test'])
20
22
  end
21
23
 
22
24
  it "should prepare array" do
23
- @obj.length.should eql(1)
25
+ expect(@obj.length).to eql(1)
24
26
  end
25
27
 
26
28
  it "should set owner and property" do
27
- @obj.casted_by.should eql(owner)
28
- @obj.casted_by_property.should eql(@prop)
29
+ expect(@obj.casted_by).to eql(owner)
30
+ expect(@obj.casted_by_property).to eql(property)
29
31
  end
30
32
 
31
33
  it "should instantiate and cast each value" do
32
- @obj.first.should eql("test")
33
- @obj.first.class.should eql(String)
34
+ expect(@obj.first).to eql("test")
35
+ expect(@obj.first.class).to eql(String)
34
36
  end
35
37
  end
36
38
 
37
39
  describe "adding to array" do
38
-
39
- before :each do
40
- @prop = Hashme::Property.new(:item, submodel)
41
- @obj = Hashme::CastedArray.new(owner, @prop, [{:name => 'test'}])
40
+ subject do
41
+ Hashme::CastedArray.new(property, owner, [{:name => 'test'}])
42
+ end
43
+ let :property do
44
+ Hashme::Property.new(:item, submodel)
42
45
  end
43
46
 
44
47
  it "should cast new items" do
45
- @obj << {:name => 'test2'}
46
- @obj.last.class.should eql(submodel)
47
- @obj.first.name.should eql('test')
48
- @obj.last.name.should eql('test2')
48
+ subject << {:name => 'test2'}
49
+ expect(subject.last.class).to eql(submodel)
50
+ expect(subject.first.name).to eql('test')
51
+ expect(subject.last.name).to eql('test2')
49
52
 
50
- @obj.last.casted_by.should eql(owner)
51
- @obj.last.casted_by_property.should eql(@prop)
53
+ expect(subject.last.casted_by).to be(subject)
54
+ expect(subject.last.casted_by_property).to eql(property)
52
55
  end
53
56
 
54
57
  end
@@ -23,7 +23,7 @@ describe Hashme::Properties do
23
23
  describe "#get_attribute" do
24
24
  it "should provide object in model" do
25
25
  @obj[:key1] = 'value'
26
- @obj.get_attribute(:key1).should eql('value')
26
+ expect(@obj.get_attribute(:key1)).to eql('value')
27
27
  end
28
28
  end
29
29
 
@@ -31,41 +31,41 @@ describe Hashme::Properties do
31
31
  it "should be posible to set attribute not defined as property" do
32
32
  @obj.set_attribute('key1', 'value1')
33
33
  @obj.set_attribute(:key2, 'value2')
34
- @obj[:key1].should eql('value1')
35
- @obj[:key2].should eql('value2')
34
+ expect(@obj[:key1]).to eql('value1')
35
+ expect(@obj[:key2]).to eql('value2')
36
36
  end
37
37
 
38
38
  it "should set and cast attribute with property" do
39
39
  property = @model.send(:properties)[:name]
40
40
  name = "Fred Flinstone"
41
- property.should_receive(:cast).with(@obj, name).and_return(name)
41
+ expect(property).to receive(:build).with(@obj, name).and_return(name)
42
42
  @obj.set_attribute(:name, name)
43
- @obj[:name].should eql(name)
43
+ expect(@obj[:name]).to eql(name)
44
44
  end
45
45
  end
46
46
 
47
47
  describe ".properties" do
48
48
 
49
49
  it "should be instantiated after property set" do
50
- @model.properties.should_not be_nil
51
- @model.properties.class.should eql(Hash)
50
+ expect(@model.properties).to_not be_nil
51
+ expect(@model.properties.class).to eql(Hash)
52
52
  end
53
53
 
54
54
  it "should be empty if no properties" do
55
55
  model = Class.new do
56
56
  include Hashme
57
57
  end
58
- model.properties.should be_empty
58
+ expect(model.properties).to be_empty
59
59
  end
60
60
 
61
61
  it "should be inherited from parent models" do
62
62
  mod = Class.new(@model) do
63
63
  property :surname, String
64
64
  end
65
- mod.properties.keys.should include(:name)
66
- mod.properties.keys.should include(:surname)
65
+ expect(mod.properties.keys).to include(:name)
66
+ expect(mod.properties.keys).to include(:surname)
67
67
  # Make sure we don't update the parent!
68
- @model.properties.keys.should_not include(:surname)
68
+ expect(@model.properties.keys).to_not include(:surname)
69
69
  end
70
70
 
71
71
  end
@@ -73,36 +73,36 @@ describe Hashme::Properties do
73
73
  describe ".property" do
74
74
 
75
75
  it "should fail if no type is defined" do
76
- @model.properties.length.should eql(1)
76
+ expect(@model.properties.length).to eql(1)
77
77
  expect {
78
78
  @model.property :foobar
79
79
  }.to raise_error(ArgumentError)
80
- @model.properties.length.should eql(1)
80
+ expect(@model.properties.length).to eql(1)
81
81
  end
82
82
 
83
83
  it "should create a new property with helper methods" do
84
- @model.properties.length.should eql(1)
84
+ expect(@model.properties.length).to eql(1)
85
85
  @model.property :desc, String
86
- @model.properties.length.should eql(2)
86
+ expect(@model.properties.length).to eql(2)
87
87
 
88
88
  prop = @model.properties[:desc]
89
- prop.class.should eql(Hashme::Property)
89
+ expect(prop.class).to eql(Hashme::Property)
90
90
 
91
- @obj.should respond_to(:desc)
92
- @obj.should respond_to(:desc=)
91
+ expect(@obj).to respond_to(:desc)
92
+ expect(@obj).to respond_to(:desc=)
93
93
 
94
94
  @obj.desc = "test"
95
- @obj.desc.should eql("test")
95
+ expect(@obj.desc).to eql("test")
96
96
  end
97
97
 
98
98
  it "should return nil on property with no default" do
99
99
  @model.property :nickname, String
100
- @obj.nickname.should be_nil
100
+ expect(@obj.nickname).to be_nil
101
101
  end
102
102
 
103
103
  it "should create helper method with support for default values" do
104
104
  @model.property :name, String, :default => "Sam"
105
- @obj.name.should eql("Sam")
105
+ expect(@obj.name).to eql("Sam")
106
106
  end
107
107
 
108
108
  end
@@ -0,0 +1,612 @@
1
+ require 'spec_helper'
2
+
3
+ class Course
4
+ include Hashme
5
+
6
+ property :title, String
7
+ property :participants, [Object]
8
+ property :ends_at, Time
9
+ property :estimate, Float
10
+ property :hours, Integer
11
+ property :profit, BigDecimal
12
+ property :started_on, Date
13
+ property :updated_at, DateTime
14
+ property :active, TrueClass
15
+ property :very_active, TrueClass
16
+ property :klass, Class
17
+ property :currency, String, :default => 'EUR'
18
+ property :symbol, Symbol
19
+ end
20
+
21
+ describe Hashme::PropertyCasting do
22
+
23
+ let :property do
24
+ double(:property)
25
+ end
26
+
27
+ describe "#cast" do
28
+ it "should respond" do
29
+ expect(subject).to respond_to(:cast)
30
+ end
31
+ end
32
+
33
+ let :course do
34
+ Course.new(:title => 'Relaxation')
35
+ end
36
+
37
+ describe "when value is nil" do
38
+ it "leaves the value unchanged" do
39
+ course.title = nil
40
+ expect(course['title']).to be_nil
41
+ end
42
+ end
43
+
44
+ describe "when value is empty string" do
45
+ it "leaves the value unchanged" do
46
+ course.title = ""
47
+ expect(course['title']).to eql("")
48
+ end
49
+ end
50
+
51
+ describe "when type primitive is an Object" do
52
+ it "it should not cast given value" do
53
+ course.participants = [{}, 'q', 1]
54
+ expect(course['participants']).to eql([{}, 'q', 1])
55
+ end
56
+
57
+ it "should cast started_on to Date" do
58
+ course.started_on = Date.today
59
+ expect(course['started_on']).to be_an_instance_of(Date)
60
+ end
61
+ end
62
+
63
+ describe "when type primitive is a String" do
64
+ it "keeps string value unchanged" do
65
+ value = "1.0"
66
+ course.title = value
67
+ expect(course['title']).to equal(value)
68
+ end
69
+
70
+ it "it casts to string representation of the value" do
71
+ course.title = 1.0
72
+ expect(course['title']).to eql("1.0")
73
+ end
74
+ end
75
+
76
+ describe "when type primitive is a Symbol" do
77
+ it "keeps symbol value unchanged" do
78
+ value = :a_symbol
79
+ course.symbol = value
80
+ expect(course['symbol']).to be(value)
81
+ end
82
+
83
+ it "it casts to symbol representation of the value" do
84
+ course.symbol = "a_symbol"
85
+ expect(course['symbol']).to be(:a_symbol)
86
+ end
87
+
88
+ it "turns blank value into nil" do
89
+ course.symbol = ""
90
+ expect(course.symbol).to be_nil
91
+ end
92
+ end
93
+
94
+
95
+ describe 'when type primitive is a Float' do
96
+ it 'returns same value if a float' do
97
+ value = 24.0
98
+ course.estimate = value
99
+ expect(course['estimate']).to equal(value)
100
+ end
101
+
102
+ it 'returns float representation of a zero string integer' do
103
+ course.estimate = '0'
104
+ expect(course['estimate']).to eql(0.0)
105
+ end
106
+
107
+ it 'returns float representation of a positive string integer' do
108
+ course.estimate = '24'
109
+ expect(course['estimate']).to eql(24.0)
110
+ end
111
+
112
+ it 'returns float representation of a negative string integer' do
113
+ course.estimate = '-24'
114
+ expect(course['estimate']).to eql(-24.0)
115
+ end
116
+
117
+ it 'returns float representation of a zero string float' do
118
+ course.estimate = '0.0'
119
+ expect(course['estimate']).to eql(0.0)
120
+ end
121
+
122
+ it 'returns float representation of a positive string float' do
123
+ course.estimate = '24.35'
124
+ expect(course['estimate']).to eql(24.35)
125
+ end
126
+
127
+ it 'returns float representation of a negative string float' do
128
+ course.estimate = '-24.35'
129
+ expect(course['estimate']).to eql(-24.35)
130
+ end
131
+
132
+ it 'returns float representation of a zero string float, with no leading digits' do
133
+ course.estimate = '.0'
134
+ expect(course['estimate']).to eql(0.0)
135
+ end
136
+
137
+ it 'returns float representation of a positive string float, with no leading digits' do
138
+ course.estimate = '.41'
139
+ expect(course['estimate']).to eql(0.41)
140
+ end
141
+
142
+ it 'returns float representation of a zero integer' do
143
+ course.estimate = 0
144
+ expect(course['estimate']).to eql(0.0)
145
+ end
146
+
147
+ it 'returns float representation of a positive integer' do
148
+ course.estimate = 24
149
+ expect(course['estimate']).to eql(24.0)
150
+ end
151
+
152
+ it 'returns float representation of a negative integer' do
153
+ course.estimate = -24
154
+ expect(course['estimate']).to eql(-24.0)
155
+ end
156
+
157
+ it 'returns float representation of a zero decimal' do
158
+ course.estimate = BigDecimal('0.0')
159
+ expect(course['estimate']).to eql(0.0)
160
+ end
161
+
162
+ it 'returns float representation of a positive decimal' do
163
+ course.estimate = BigDecimal('24.35')
164
+ expect(course['estimate']).to eql(24.35)
165
+ end
166
+
167
+ it 'returns float representation of a negative decimal' do
168
+ course.estimate = BigDecimal('-24.35')
169
+ expect(course['estimate']).to eql(-24.35)
170
+ end
171
+
172
+ it 'return float of a number with commas instead of points for decimals' do
173
+ course.estimate = '23,35'
174
+ expect(course['estimate']).to eql(23.35)
175
+ end
176
+
177
+ it "should handle numbers with commas and points" do
178
+ course.estimate = '1,234.00'
179
+ expect(course.estimate).to eql(1234.00)
180
+ end
181
+
182
+ it "should handle a mis-match of commas and points and maintain the last one" do
183
+ course.estimate = "1,232.434.123,323"
184
+ expect(course.estimate).to eql(1232434123.323)
185
+ end
186
+
187
+ it "should handle numbers with whitespace" do
188
+ course.estimate = " 24.35 "
189
+ expect(course.estimate).to eql(24.35)
190
+ end
191
+
192
+ it "should handle numbers with unit strings" do
193
+ course.estimate = "23.21 points"
194
+ expect(course['estimate']).to eql(23.21)
195
+ end
196
+
197
+ [ '', 'string', ' foo ' ].each do |value|
198
+ it "should typecast string without a number to nil (#{value.inspect})" do
199
+ course.estimate = value
200
+ expect(course['estimate']).to be_nil
201
+ end
202
+ end
203
+
204
+ [ '00.0', '0.', '-.0' ].each do |value|
205
+ it "should typecast strings with strange numbers to zero (#{value.inspect})" do
206
+ course.estimate = value
207
+ expect(course['estimate']).to eql(0.0)
208
+ end
209
+ end
210
+
211
+ [ Object.new, true ].each do |value|
212
+ it "should not typecast non-numeric value that won't respond to #to_f (#{value.inspect})" do
213
+ course.estimate = value
214
+ expect(course['estimate']).to equal(nil)
215
+ end
216
+ end
217
+
218
+ end
219
+
220
+ describe 'when type primitive is a Integer' do
221
+ it 'returns same value if an integer' do
222
+ value = 24
223
+ course.hours = value
224
+ expect(course['hours']).to equal(value)
225
+ end
226
+
227
+ it 'returns integer representation of a zero string integer' do
228
+ course.hours = '0'
229
+ expect(course['hours']).to eql(0)
230
+ end
231
+
232
+ it 'returns integer representation of a positive string integer' do
233
+ course.hours = '24'
234
+ expect(course['hours']).to eql(24)
235
+ end
236
+
237
+ it 'returns integer representation of a negative string integer' do
238
+ course.hours = '-24'
239
+ expect(course['hours']).to eql(-24)
240
+ end
241
+
242
+ it 'returns integer representation of a zero string float' do
243
+ course.hours = '0.0'
244
+ expect(course['hours']).to eql(0)
245
+ end
246
+
247
+ it 'returns integer representation of a positive string float' do
248
+ course.hours = '24.35'
249
+ expect(course['hours']).to eql(24)
250
+ end
251
+
252
+ it 'returns integer representation of a negative string float' do
253
+ course.hours = '-24.35'
254
+ expect(course['hours']).to eql(-24)
255
+ end
256
+
257
+ it 'returns integer representation of a zero string float, with no leading digits' do
258
+ course.hours = '.0'
259
+ expect(course['hours']).to eql(0)
260
+ end
261
+
262
+ it 'returns integer representation of a positive string float, with no leading digits' do
263
+ course.hours = '.41'
264
+ expect(course['hours']).to eql(0)
265
+ end
266
+
267
+ it 'returns integer representation of a zero float' do
268
+ course.hours = 0.0
269
+ expect(course['hours']).to eql(0)
270
+ end
271
+
272
+ it 'returns integer representation of a positive float' do
273
+ course.hours = 24.35
274
+ expect(course['hours']).to eql(24)
275
+ end
276
+
277
+ it 'returns integer representation of a negative float' do
278
+ course.hours = -24.35
279
+ expect(course['hours']).to eql(-24)
280
+ end
281
+
282
+ it 'returns integer representation of a zero decimal' do
283
+ course.hours = '0.0'
284
+ expect(course['hours']).to eql(0)
285
+ end
286
+
287
+ it 'returns integer representation of a positive decimal' do
288
+ course.hours = '24.35'
289
+ expect(course['hours']).to eql(24)
290
+ end
291
+
292
+ it 'returns integer representation of a negative decimal' do
293
+ course.hours = '-24.35'
294
+ expect(course['hours']).to eql(-24)
295
+ end
296
+
297
+ it "should handle numbers with whitespace" do
298
+ course.hours = " 24 "
299
+ expect(course['hours']).to eql(24)
300
+ end
301
+
302
+ it "should handle numbers with string units" do
303
+ course.hours = "23 hours"
304
+ expect(course['hours']).to eql(23)
305
+ end
306
+
307
+ it "should typecast an empty string to nil" do
308
+ course.hours = ""
309
+ expect(course['hours']).to be_nil
310
+ end
311
+
312
+ [ '', 'string', ' foo ' ].each do |value|
313
+ it "should typecast string without a number to nil (#{value.inspect})" do
314
+ course.hours = value
315
+ expect(course['hours']).to be_nil
316
+ end
317
+ end
318
+
319
+ [ '00.0', '0.', '-.0' ].each do |value|
320
+ it "should typecast strings with strange numbers to zero (#{value.inspect})" do
321
+ course.hours = value
322
+ expect(course['hours']).to eql(0)
323
+ end
324
+ end
325
+
326
+ [ Object.new, true ].each do |value|
327
+ it "should not typecast non-numeric value that won't respond to #to_i (#{value.inspect})" do
328
+ course.hours = value
329
+ expect(course['hours']).to equal(nil)
330
+ end
331
+ end
332
+
333
+ end
334
+
335
+ describe 'when type primitive is a BigDecimal' do
336
+ it 'returns same value if a decimal' do
337
+ value = BigDecimal('24.0')
338
+ course.profit = value
339
+ expect(course['profit']).to equal(value)
340
+ end
341
+
342
+ it 'returns decimal representation of a zero string integer' do
343
+ course.profit = '0'
344
+ expect(course['profit']).to eql(BigDecimal('0.0'))
345
+ end
346
+
347
+ it 'returns decimal representation of a positive string integer' do
348
+ course.profit = '24'
349
+ expect(course['profit']).to eql(BigDecimal('24.0'))
350
+ end
351
+
352
+ it 'returns decimal representation of a negative string integer' do
353
+ course.profit = '-24'
354
+ expect(course['profit']).to eql(BigDecimal('-24.0'))
355
+ end
356
+
357
+ it 'returns decimal representation of a zero string float' do
358
+ course.profit = '0.0'
359
+ expect(course['profit']).to eql(BigDecimal('0.0'))
360
+ end
361
+
362
+ it 'returns decimal representation of a positive string float' do
363
+ course.profit = '24.35'
364
+ expect(course['profit']).to eql(BigDecimal('24.35'))
365
+ end
366
+
367
+ it 'returns decimal representation of a negative string float' do
368
+ course.profit = '-24.35'
369
+ expect(course['profit']).to eql(BigDecimal('-24.35'))
370
+ end
371
+
372
+ it 'returns decimal representation of a zero string float, with no leading digits' do
373
+ course.profit = '.0'
374
+ expect(course['profit']).to eql(BigDecimal('0.0'))
375
+ end
376
+
377
+ it 'returns decimal representation of a positive string float, with no leading digits' do
378
+ course.profit = '.41'
379
+ expect(course['profit']).to eql(BigDecimal('0.41'))
380
+ end
381
+
382
+ it 'returns decimal representation of a zero integer' do
383
+ course.profit = 0
384
+ expect(course['profit']).to eql(BigDecimal('0.0'))
385
+ end
386
+
387
+ it 'returns decimal representation of a positive integer' do
388
+ course.profit = 24
389
+ expect(course['profit']).to eql(BigDecimal('24.0'))
390
+ end
391
+
392
+ it 'returns decimal representation of a negative integer' do
393
+ course.profit = -24
394
+ expect(course['profit']).to eql(BigDecimal('-24.0'))
395
+ end
396
+
397
+ it 'returns decimal representation of a zero float' do
398
+ course.profit = 0.0
399
+ expect(course['profit']).to eql(BigDecimal('0.0'))
400
+ end
401
+
402
+ it 'returns decimal representation of a positive float' do
403
+ course.profit = 24.35
404
+ expect(course['profit']).to eql(BigDecimal('24.35'))
405
+ end
406
+
407
+ it 'returns decimal representation of a negative float' do
408
+ course.profit = -24.35
409
+ expect(course['profit']).to eql(BigDecimal('-24.35'))
410
+ end
411
+
412
+ it "should handle numbers with whitespace" do
413
+ course.profit = " 24.35 "
414
+ expect(course['profit']).to eql(BigDecimal('24.35'))
415
+ end
416
+
417
+ it "should handle numbers with strings" do
418
+ course.profit = "22.23 euros"
419
+ expect(course['profit']).to eql(BigDecimal('22.23'))
420
+ end
421
+
422
+ it "should typecast an empty string to nil" do
423
+ course.profit = ""
424
+ expect(course['profit']).to be_nil
425
+ end
426
+
427
+ [ '', 'string', ' foo ' ].each do |value|
428
+ it "should typecast string without a number to nil (#{value.inspect})" do
429
+ course.profit = value
430
+ expect(course['profit']).to be_nil
431
+ end
432
+ end
433
+
434
+ [ '00.0', '0.', '-.0' ].each do |value|
435
+ it "should typecast strings with strange numbers to zero (#{value.inspect})" do
436
+ course.profit = value
437
+ expect(course['profit']).to eql(0.0)
438
+ end
439
+ end
440
+
441
+ [ Object.new, true ].each do |value|
442
+ it "should typecast non-numeric value that won't respond to to_d (#{value.inspect}) as nil" do
443
+ course.profit = value
444
+ expect(course['profit']).to equal(nil)
445
+ end
446
+ end
447
+
448
+ end
449
+
450
+ describe 'when type primitive is a DateTime' do
451
+ describe 'and value given as a hash with keys like :year, :month, etc' do
452
+ it 'builds a DateTime instance from hash values' do
453
+ course.updated_at = {
454
+ :year => '2006',
455
+ :month => '11',
456
+ :day => '23',
457
+ :hour => '12',
458
+ :min => '0',
459
+ :sec => '0'
460
+ }
461
+ result = course['updated_at']
462
+
463
+ expect(result).to be_kind_of(DateTime)
464
+ expect(result.year).to eql(2006)
465
+ expect(result.month).to eql(11)
466
+ expect(result.day).to eql(23)
467
+ expect(result.hour).to eql(12)
468
+ expect(result.min).to eql(0)
469
+ expect(result.sec).to eql(0)
470
+ end
471
+ end
472
+
473
+ describe 'and value is a string' do
474
+ it 'parses the string' do
475
+ course.updated_at = 'Dec, 2006'
476
+ expect(course['updated_at'].month).to eql(12)
477
+ end
478
+ end
479
+
480
+ it 'does not typecast non-datetime values' do
481
+ course.updated_at = 'not-datetime'
482
+ expect(course['updated_at']).to be_nil
483
+ end
484
+ end
485
+
486
+ describe 'when type primitive is a Date' do
487
+ describe 'and value given as a hash with keys like :year, :month, etc' do
488
+ it 'builds a Date instance from hash values' do
489
+ course.started_on = {
490
+ :year => '2007',
491
+ :month => '3',
492
+ :day => '25'
493
+ }
494
+ result = course['started_on']
495
+
496
+ expect(result).to be_kind_of(Date)
497
+ expect(result.year).to eql(2007)
498
+ expect(result.month).to eql(3)
499
+ expect(result.day).to eql(25)
500
+ end
501
+ end
502
+
503
+ describe 'and value is a string' do
504
+ it 'parses the string' do
505
+ course.started_on = 'Dec 20th, 2006'
506
+ expect(course.started_on.month).to eql(12)
507
+ expect(course.started_on.day).to eql(20)
508
+ expect(course.started_on.year).to eql(2006)
509
+ end
510
+ end
511
+
512
+ it 'does not typecast non-date values' do
513
+ course.started_on = 'not-date'
514
+ expect(course['started_on']).to be_nil
515
+ end
516
+ end
517
+
518
+ describe 'when type primitive is a Time' do
519
+ describe 'and value given as a hash with keys like :year, :month, etc' do
520
+ it 'builds a Time instance from hash values' do
521
+ course.ends_at = {
522
+ :year => '2006',
523
+ :month => '11',
524
+ :day => '23',
525
+ :hour => '12',
526
+ :min => '0',
527
+ :sec => '0'
528
+ }
529
+ result = course['ends_at']
530
+
531
+ expect(result).to be_kind_of(Time)
532
+ expect(result.year).to eql(2006)
533
+ expect(result.month).to eql(11)
534
+ expect(result.day).to eql(23)
535
+ expect(result.hour).to eql(12)
536
+ expect(result.min).to eql(0)
537
+ expect(result.sec).to eql(0)
538
+ end
539
+ end
540
+
541
+ describe 'and value is a string' do
542
+ it 'parses the string' do
543
+ t = Time.new(2011, 4, 1, 18, 50, 32, "+02:00")
544
+ course.ends_at = t.strftime('%Y/%m/%d %H:%M:%S %z')
545
+ expect(course['ends_at'].year).to eql(t.year)
546
+ expect(course['ends_at'].month).to eql(t.month)
547
+ expect(course['ends_at'].day).to eql(t.day)
548
+ expect(course['ends_at'].hour).to eql(t.hour)
549
+ expect(course['ends_at'].min).to eql(t.min)
550
+ expect(course['ends_at'].sec).to eql(t.sec)
551
+ end
552
+ it 'parses the string without offset as UTC' do
553
+ t = Time.now.utc
554
+ course.ends_at = t.strftime("%Y-%m-%d %H:%M:%S")
555
+ expect(course.ends_at.utc?).to be_truthy
556
+ expect(course['ends_at'].year).to eql(t.year)
557
+ expect(course['ends_at'].month).to eql(t.month)
558
+ expect(course['ends_at'].day).to eql(t.day)
559
+ expect(course['ends_at'].hour).to eql(t.hour)
560
+ expect(course['ends_at'].min).to eql(t.min)
561
+ expect(course['ends_at'].sec).to eql(t.sec)
562
+ end
563
+ end
564
+
565
+ it 'does not typecast non-time values' do
566
+ course.ends_at = 'not-time'
567
+ expect(course['ends_at']).to be_nil
568
+ end
569
+ end
570
+
571
+ describe 'when type primitive is a Class' do
572
+ it 'returns same value if a class' do
573
+ value = Course
574
+ course.klass = value
575
+ expect(course['klass']).to equal(value)
576
+ end
577
+
578
+ it 'returns the class if found' do
579
+ course.klass = 'Course'
580
+ expect(course['klass']).to eql(Course)
581
+ end
582
+
583
+ it 'does not typecast non-class values' do
584
+ course.klass = 'NoClass'
585
+ expect(course['klass']).to be_nil
586
+ end
587
+ end
588
+
589
+ describe 'when type primitive is a Boolean' do
590
+
591
+ [ true, 'true', 'TRUE', '1', 1, 't', 'T' ].each do |value|
592
+ it "returns true when value is #{value.inspect}" do
593
+ course.active = value
594
+ expect(course['active']).to be_truthy
595
+ end
596
+ end
597
+
598
+ [ false, 'false', 'FALSE', '0', 0, 'f', 'F' ].each do |value|
599
+ it "returns false when value is #{value.inspect}" do
600
+ course.active = value
601
+ expect(course['active']).to be_falsey
602
+ end
603
+ end
604
+
605
+ [ 'string', 2, 1.0, BigDecimal('1.0'), DateTime.now, Time.now, Date.today, Class, Object.new, ].each do |value|
606
+ it "does not typecast value #{value.inspect}" do
607
+ course.active = value
608
+ expect(course['active']).to be_nil
609
+ end
610
+ end
611
+ end
612
+ end