couchrest 0.35 → 0.36
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.
- data/Rakefile +2 -2
- data/history.txt +10 -0
- data/lib/couchrest.rb +15 -12
- data/lib/couchrest/core/database.rb +25 -7
- data/lib/couchrest/mixins/collection.rb +45 -9
- data/lib/couchrest/mixins/properties.rb +11 -53
- data/lib/couchrest/monkeypatches.rb +1 -1
- data/lib/couchrest/more/extended_document.rb +5 -4
- data/lib/couchrest/more/property.rb +8 -9
- data/lib/couchrest/more/typecast.rb +180 -0
- data/lib/couchrest/validation/validators/required_field_validator.rb +2 -2
- data/spec/couchrest/core/couchrest_spec.rb +16 -79
- data/spec/couchrest/core/database_spec.rb +70 -3
- data/spec/couchrest/more/casted_model_spec.rb +1 -1
- data/spec/couchrest/more/extended_doc_spec.rb +58 -7
- data/spec/couchrest/more/property_spec.rb +424 -85
- data/spec/fixtures/more/article.rb +2 -2
- data/spec/fixtures/more/course.rb +13 -5
- data/spec/fixtures/more/event.rb +1 -2
- data/spec/fixtures/more/person.rb +1 -1
- data/spec/fixtures/more/question.rb +1 -1
- data/spec/fixtures/more/service.rb +1 -1
- data/spec/spec_helper.rb +13 -1
- metadata +27 -13
@@ -12,7 +12,7 @@ class WithCastedModelMixin < Hash
|
|
12
12
|
include CouchRest::CastedModel
|
13
13
|
property :name
|
14
14
|
property :no_value
|
15
|
-
property :details,
|
15
|
+
property :details, :type => 'Object', :default => {}
|
16
16
|
property :casted_attribute, :cast_as => 'WithCastedModelMixin'
|
17
17
|
end
|
18
18
|
|
@@ -9,11 +9,11 @@ describe "ExtendedDocument" do
|
|
9
9
|
|
10
10
|
class WithDefaultValues < CouchRest::ExtendedDocument
|
11
11
|
use_database TEST_SERVER.default_database
|
12
|
-
property :preset,
|
13
|
-
property :set_by_proc,
|
14
|
-
property :tags,
|
12
|
+
property :preset, :type => 'Object', :default => {:right => 10, :top_align => false}
|
13
|
+
property :set_by_proc, :default => Proc.new{Time.now}, :cast_as => 'Time'
|
14
|
+
property :tags, :type => ['String'], :default => []
|
15
15
|
property :read_only_with_default, :default => 'generic', :read_only => true
|
16
|
-
property :default_false, :default => false
|
16
|
+
property :default_false, :type => 'Boolean', :default => false
|
17
17
|
property :name
|
18
18
|
timestamps!
|
19
19
|
end
|
@@ -104,6 +104,18 @@ describe "ExtendedDocument" do
|
|
104
104
|
self.other_arg = "foo-#{value}"
|
105
105
|
end
|
106
106
|
end
|
107
|
+
|
108
|
+
class WithAfterInitializeMethod < CouchRest::ExtendedDocument
|
109
|
+
use_database TEST_SERVER.default_database
|
110
|
+
|
111
|
+
property :some_value
|
112
|
+
|
113
|
+
def after_initialize
|
114
|
+
self.some_value ||= "value"
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
107
119
|
|
108
120
|
before(:each) do
|
109
121
|
@obj = WithDefaultValues.new
|
@@ -383,7 +395,7 @@ describe "ExtendedDocument" do
|
|
383
395
|
"professor" => {
|
384
396
|
"name" => ["Mark", "Hinchliff"]
|
385
397
|
},
|
386
|
-
"
|
398
|
+
"ends_at" => "2008/12/19 13:00:00 +0800"
|
387
399
|
}
|
388
400
|
r = Course.database.save_doc course_doc
|
389
401
|
@course = Course.get r['id']
|
@@ -394,8 +406,8 @@ describe "ExtendedDocument" do
|
|
394
406
|
it "should instantiate the professor as a person" do
|
395
407
|
@course['professor'].last_name.should == "Hinchliff"
|
396
408
|
end
|
397
|
-
it "should instantiate the
|
398
|
-
@course['
|
409
|
+
it "should instantiate the ends_at as a Time" do
|
410
|
+
@course['ends_at'].should == Time.parse("2008/12/19 13:00:00 +0800")
|
399
411
|
end
|
400
412
|
end
|
401
413
|
|
@@ -698,6 +710,13 @@ describe "ExtendedDocument" do
|
|
698
710
|
@doc.other_arg.should == "foo-foo"
|
699
711
|
end
|
700
712
|
end
|
713
|
+
|
714
|
+
describe "initialization" do
|
715
|
+
it "should call after_initialize method if available" do
|
716
|
+
@doc = WithAfterInitializeMethod.new
|
717
|
+
@doc['some_value'].should eql('value')
|
718
|
+
end
|
719
|
+
end
|
701
720
|
|
702
721
|
describe "recursive validation on an extended document" do
|
703
722
|
before :each do
|
@@ -743,4 +762,36 @@ describe "ExtendedDocument" do
|
|
743
762
|
cat.save.should be_true
|
744
763
|
end
|
745
764
|
end
|
765
|
+
|
766
|
+
describe "searching the contents of an extended document" do
|
767
|
+
before :each do
|
768
|
+
@db = reset_test_db!
|
769
|
+
|
770
|
+
names = ["Fuzzy", "Whiskers", "Mr Bigglesworth", "Sockington", "Smitty", "Sammy", "Samson", "Simon"]
|
771
|
+
names.each { |name| Cat.create(:name => name) }
|
772
|
+
|
773
|
+
search_function = { 'defaults' => {'store' => 'no', 'index' => 'analyzed_no_norms'},
|
774
|
+
'index' => "function(doc) { ret = new Document(); ret.add(doc['name'], {'field':'name'}); return ret; }" }
|
775
|
+
@db.save_doc({'_id' => '_design/search', 'fulltext' => {'cats' => search_function}})
|
776
|
+
end
|
777
|
+
|
778
|
+
it "should be able to paginate through a large set of search results" do
|
779
|
+
if couchdb_lucene_available?
|
780
|
+
names = []
|
781
|
+
Cat.paginated_each(:design_doc => "search", :view_name => "cats",
|
782
|
+
:q => 'name:S*', :search => true, :include_docs => true, :per_page => 3) do |cat|
|
783
|
+
cat.should_not be_nil
|
784
|
+
names << cat.name
|
785
|
+
end
|
786
|
+
|
787
|
+
names.size.should == 5
|
788
|
+
names.should include('Sockington')
|
789
|
+
names.should include('Smitty')
|
790
|
+
names.should include('Sammy')
|
791
|
+
names.should include('Samson')
|
792
|
+
names.should include('Simon')
|
793
|
+
end
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|
746
797
|
end
|
@@ -7,6 +7,7 @@ require File.join(FIXTURE_PATH, 'more', 'service')
|
|
7
7
|
require File.join(FIXTURE_PATH, 'more', 'event')
|
8
8
|
require File.join(FIXTURE_PATH, 'more', 'cat')
|
9
9
|
require File.join(FIXTURE_PATH, 'more', 'user')
|
10
|
+
require File.join(FIXTURE_PATH, 'more', 'course')
|
10
11
|
|
11
12
|
|
12
13
|
describe "ExtendedDocument properties" do
|
@@ -42,11 +43,11 @@ describe "ExtendedDocument properties" do
|
|
42
43
|
|
43
44
|
it "should let you use an alias for a casted attribute" do
|
44
45
|
@card.cast_alias = Person.new(:name => "Aimonetti")
|
45
|
-
@card.cast_alias.name.should == "Aimonetti"
|
46
|
-
@card.calias.name.should == "Aimonetti"
|
46
|
+
@card.cast_alias.name.should == ["Aimonetti"]
|
47
|
+
@card.calias.name.should == ["Aimonetti"]
|
47
48
|
card = Card.new(:first_name => "matt", :cast_alias => {:name => "Aimonetti"})
|
48
|
-
card.cast_alias.name.should == "Aimonetti"
|
49
|
-
card.calias.name.should == "Aimonetti"
|
49
|
+
card.cast_alias.name.should == ["Aimonetti"]
|
50
|
+
card.calias.name.should == ["Aimonetti"]
|
50
51
|
end
|
51
52
|
|
52
53
|
it "should be auto timestamped" do
|
@@ -155,110 +156,448 @@ describe "ExtendedDocument properties" do
|
|
155
156
|
end
|
156
157
|
end
|
157
158
|
end
|
158
|
-
|
159
|
+
|
159
160
|
describe "casting" do
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
e = Event.database.save_doc event_doc
|
161
|
+
before(:each) do
|
162
|
+
@course = Course.new(:title => 'Relaxation')
|
163
|
+
end
|
164
164
|
|
165
|
-
|
165
|
+
describe "when value is nil" do
|
166
|
+
it "leaves the value unchanged" do
|
167
|
+
@course.title = nil
|
168
|
+
@course['title'].should == nil
|
166
169
|
end
|
167
|
-
|
168
|
-
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "when type primitive is an Object" do
|
173
|
+
it "it should not cast given value" do
|
174
|
+
@course.participants = [{}, 'q', 1]
|
175
|
+
@course['participants'].should == [{}, 'q', 1]
|
169
176
|
end
|
170
|
-
|
171
|
-
|
177
|
+
|
178
|
+
it "should cast started_on to Date" do
|
179
|
+
@course.started_on = Date.today
|
180
|
+
@course['started_on'].should be_an_instance_of(Date)
|
172
181
|
end
|
173
182
|
end
|
174
183
|
|
175
|
-
describe "
|
176
|
-
|
177
|
-
|
178
|
-
|
184
|
+
describe "when type primitive is a String" do
|
185
|
+
it "keeps string value unchanged" do
|
186
|
+
value = "1.0"
|
187
|
+
@course.title = value
|
188
|
+
@course['title'].should equal(value)
|
179
189
|
end
|
180
190
|
|
181
|
-
it "
|
182
|
-
|
183
|
-
|
184
|
-
RootBeerFloat.new(:price => '-9').price.should == -9.0
|
191
|
+
it "it casts to string representation of the value" do
|
192
|
+
@course.title = 1.0
|
193
|
+
@course['title'].should eql("1.0")
|
185
194
|
end
|
186
|
-
|
187
|
-
|
188
|
-
|
195
|
+
end
|
196
|
+
|
197
|
+
describe 'when type primitive is a Float' do
|
198
|
+
it 'returns same value if a float' do
|
199
|
+
value = 24.0
|
200
|
+
@course.estimate = value
|
201
|
+
@course['estimate'].should equal(value)
|
189
202
|
end
|
190
|
-
|
191
|
-
it
|
192
|
-
|
203
|
+
|
204
|
+
it 'returns float representation of a zero string integer' do
|
205
|
+
@course.estimate = '0'
|
206
|
+
@course['estimate'].should eql(0.0)
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'returns float representation of a positive string integer' do
|
210
|
+
@course.estimate = '24'
|
211
|
+
@course['estimate'].should eql(24.0)
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'returns float representation of a negative string integer' do
|
215
|
+
@course.estimate = '-24'
|
216
|
+
@course['estimate'].should eql(-24.0)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'returns float representation of a zero string float' do
|
220
|
+
@course.estimate = '0.0'
|
221
|
+
@course['estimate'].should eql(0.0)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'returns float representation of a positive string float' do
|
225
|
+
@course.estimate = '24.35'
|
226
|
+
@course['estimate'].should eql(24.35)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'returns float representation of a negative string float' do
|
230
|
+
@course.estimate = '-24.35'
|
231
|
+
@course['estimate'].should eql(-24.35)
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'returns float representation of a zero string float, with no leading digits' do
|
235
|
+
@course.estimate = '.0'
|
236
|
+
@course['estimate'].should eql(0.0)
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'returns float representation of a positive string float, with no leading digits' do
|
240
|
+
@course.estimate = '.41'
|
241
|
+
@course['estimate'].should eql(0.41)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'returns float representation of a zero integer' do
|
245
|
+
@course.estimate = 0
|
246
|
+
@course['estimate'].should eql(0.0)
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'returns float representation of a positive integer' do
|
250
|
+
@course.estimate = 24
|
251
|
+
@course['estimate'].should eql(24.0)
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'returns float representation of a negative integer' do
|
255
|
+
@course.estimate = -24
|
256
|
+
@course['estimate'].should eql(-24.0)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'returns float representation of a zero decimal' do
|
260
|
+
@course.estimate = BigDecimal('0.0')
|
261
|
+
@course['estimate'].should eql(0.0)
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'returns float representation of a positive decimal' do
|
265
|
+
@course.estimate = BigDecimal('24.35')
|
266
|
+
@course['estimate'].should eql(24.35)
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'returns float representation of a negative decimal' do
|
270
|
+
@course.estimate = BigDecimal('-24.35')
|
271
|
+
@course['estimate'].should eql(-24.35)
|
272
|
+
end
|
273
|
+
|
274
|
+
[ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |value|
|
275
|
+
it "does not typecast non-numeric value #{value.inspect}" do
|
276
|
+
@course.estimate = value
|
277
|
+
@course['estimate'].should equal(value)
|
278
|
+
end
|
193
279
|
end
|
194
280
|
end
|
195
|
-
|
196
|
-
describe
|
197
|
-
|
198
|
-
|
199
|
-
|
281
|
+
|
282
|
+
describe 'when type primitive is a Integer' do
|
283
|
+
it 'returns same value if an integer' do
|
284
|
+
value = 24
|
285
|
+
@course.hours = value
|
286
|
+
@course['hours'].should equal(value)
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'returns integer representation of a zero string integer' do
|
290
|
+
@course.hours = '0'
|
291
|
+
@course['hours'].should eql(0)
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'returns integer representation of a positive string integer' do
|
295
|
+
@course.hours = '24'
|
296
|
+
@course['hours'].should eql(24)
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'returns integer representation of a negative string integer' do
|
300
|
+
@course.hours = '-24'
|
301
|
+
@course['hours'].should eql(-24)
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'returns integer representation of a zero string float' do
|
305
|
+
@course.hours = '0.0'
|
306
|
+
@course['hours'].should eql(0)
|
307
|
+
end
|
308
|
+
|
309
|
+
it 'returns integer representation of a positive string float' do
|
310
|
+
@course.hours = '24.35'
|
311
|
+
@course['hours'].should eql(24)
|
312
|
+
end
|
313
|
+
|
314
|
+
it 'returns integer representation of a negative string float' do
|
315
|
+
@course.hours = '-24.35'
|
316
|
+
@course['hours'].should eql(-24)
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'returns integer representation of a zero string float, with no leading digits' do
|
320
|
+
@course.hours = '.0'
|
321
|
+
@course['hours'].should eql(0)
|
200
322
|
end
|
201
323
|
|
202
|
-
it
|
203
|
-
|
204
|
-
|
205
|
-
|
324
|
+
it 'returns integer representation of a positive string float, with no leading digits' do
|
325
|
+
@course.hours = '.41'
|
326
|
+
@course['hours'].should eql(0)
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'returns integer representation of a zero float' do
|
330
|
+
@course.hours = 0.0
|
331
|
+
@course['hours'].should eql(0)
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'returns integer representation of a positive float' do
|
335
|
+
@course.hours = 24.35
|
336
|
+
@course['hours'].should eql(24)
|
337
|
+
end
|
338
|
+
|
339
|
+
it 'returns integer representation of a negative float' do
|
340
|
+
@course.hours = -24.35
|
341
|
+
@course['hours'].should eql(-24)
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'returns integer representation of a zero decimal' do
|
345
|
+
@course.hours = '0.0'
|
346
|
+
@course['hours'].should eql(0)
|
347
|
+
end
|
206
348
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
RootBeerFloat.new(:tasty => nil).tasty?.should == false
|
349
|
+
it 'returns integer representation of a positive decimal' do
|
350
|
+
@course.hours = '24.35'
|
351
|
+
@course['hours'].should eql(24)
|
211
352
|
end
|
212
353
|
|
213
|
-
it
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
354
|
+
it 'returns integer representation of a negative decimal' do
|
355
|
+
@course.hours = '-24.35'
|
356
|
+
@course['hours'].should eql(-24)
|
357
|
+
end
|
358
|
+
|
359
|
+
[ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |value|
|
360
|
+
it "does not typecast non-numeric value #{value.inspect}" do
|
361
|
+
@course.hours = value
|
362
|
+
@course['hours'].should equal(value)
|
363
|
+
end
|
220
364
|
end
|
221
365
|
end
|
222
366
|
|
223
|
-
|
224
|
-
|
367
|
+
describe 'when type primitive is a BigDecimal' do
|
368
|
+
it 'returns same value if a decimal' do
|
369
|
+
value = BigDecimal('24.0')
|
370
|
+
@course.profit = value
|
371
|
+
@course['profit'].should equal(value)
|
372
|
+
end
|
225
373
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
374
|
+
it 'returns decimal representation of a zero string integer' do
|
375
|
+
@course.profit = '0'
|
376
|
+
@course['profit'].should eql(BigDecimal('0.0'))
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'returns decimal representation of a positive string integer' do
|
380
|
+
@course.profit = '24'
|
381
|
+
@course['profit'].should eql(BigDecimal('24.0'))
|
382
|
+
end
|
383
|
+
|
384
|
+
it 'returns decimal representation of a negative string integer' do
|
385
|
+
@course.profit = '-24'
|
386
|
+
@course['profit'].should eql(BigDecimal('-24.0'))
|
387
|
+
end
|
388
|
+
|
389
|
+
it 'returns decimal representation of a zero string float' do
|
390
|
+
@course.profit = '0.0'
|
391
|
+
@course['profit'].should eql(BigDecimal('0.0'))
|
392
|
+
end
|
393
|
+
|
394
|
+
it 'returns decimal representation of a positive string float' do
|
395
|
+
@course.profit = '24.35'
|
396
|
+
@course['profit'].should eql(BigDecimal('24.35'))
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'returns decimal representation of a negative string float' do
|
400
|
+
@course.profit = '-24.35'
|
401
|
+
@course['profit'].should eql(BigDecimal('-24.35'))
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'returns decimal representation of a zero string float, with no leading digits' do
|
405
|
+
@course.profit = '.0'
|
406
|
+
@course['profit'].should eql(BigDecimal('0.0'))
|
407
|
+
end
|
408
|
+
|
409
|
+
it 'returns decimal representation of a positive string float, with no leading digits' do
|
410
|
+
@course.profit = '.41'
|
411
|
+
@course['profit'].should eql(BigDecimal('0.41'))
|
412
|
+
end
|
413
|
+
|
414
|
+
it 'returns decimal representation of a zero integer' do
|
415
|
+
@course.profit = 0
|
416
|
+
@course['profit'].should eql(BigDecimal('0.0'))
|
417
|
+
end
|
418
|
+
|
419
|
+
it 'returns decimal representation of a positive integer' do
|
420
|
+
@course.profit = 24
|
421
|
+
@course['profit'].should eql(BigDecimal('24.0'))
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'returns decimal representation of a negative integer' do
|
425
|
+
@course.profit = -24
|
426
|
+
@course['profit'].should eql(BigDecimal('-24.0'))
|
427
|
+
end
|
428
|
+
|
429
|
+
it 'returns decimal representation of a zero float' do
|
430
|
+
@course.profit = 0.0
|
431
|
+
@course['profit'].should eql(BigDecimal('0.0'))
|
432
|
+
end
|
433
|
+
|
434
|
+
it 'returns decimal representation of a positive float' do
|
435
|
+
@course.profit = 24.35
|
436
|
+
@course['profit'].should eql(BigDecimal('24.35'))
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'returns decimal representation of a negative float' do
|
440
|
+
@course.profit = -24.35
|
441
|
+
@course['profit'].should eql(BigDecimal('-24.35'))
|
442
|
+
end
|
443
|
+
|
444
|
+
[ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |value|
|
445
|
+
it "does not typecast non-numeric value #{value.inspect}" do
|
446
|
+
@course.profit = value
|
447
|
+
@course['profit'].should equal(value)
|
448
|
+
end
|
449
|
+
end
|
238
450
|
end
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
451
|
+
|
452
|
+
describe 'when type primitive is a DateTime' do
|
453
|
+
describe 'and value given as a hash with keys like :year, :month, etc' do
|
454
|
+
it 'builds a DateTime instance from hash values' do
|
455
|
+
@course.updated_at = {
|
456
|
+
:year => '2006',
|
457
|
+
:month => '11',
|
458
|
+
:day => '23',
|
459
|
+
:hour => '12',
|
460
|
+
:min => '0',
|
461
|
+
:sec => '0'
|
462
|
+
}
|
463
|
+
result = @course['updated_at']
|
464
|
+
|
465
|
+
result.should be_kind_of(DateTime)
|
466
|
+
result.year.should eql(2006)
|
467
|
+
result.month.should eql(11)
|
468
|
+
result.day.should eql(23)
|
469
|
+
result.hour.should eql(12)
|
470
|
+
result.min.should eql(0)
|
471
|
+
result.sec.should eql(0)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
describe 'and value is a string' do
|
476
|
+
it 'parses the string' do
|
477
|
+
@course.updated_at = 'Dec, 2006'
|
478
|
+
@course['updated_at'].month.should == 12
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
it 'does not typecast non-datetime values' do
|
483
|
+
@course.updated_at = 'not-datetime'
|
484
|
+
@course['updated_at'].should eql('not-datetime')
|
485
|
+
end
|
248
486
|
end
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
487
|
+
|
488
|
+
describe 'when type primitive is a Date' do
|
489
|
+
describe 'and value given as a hash with keys like :year, :month, etc' do
|
490
|
+
it 'builds a Date instance from hash values' do
|
491
|
+
@course.started_on = {
|
492
|
+
:year => '2007',
|
493
|
+
:month => '3',
|
494
|
+
:day => '25'
|
495
|
+
}
|
496
|
+
result = @course['started_on']
|
497
|
+
|
498
|
+
result.should be_kind_of(Date)
|
499
|
+
result.year.should eql(2007)
|
500
|
+
result.month.should eql(3)
|
501
|
+
result.day.should eql(25)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
describe 'and value is a string' do
|
506
|
+
it 'parses the string' do
|
507
|
+
@course.started_on = 'Dec 20th, 2006'
|
508
|
+
@course.started_on.month.should == 12
|
509
|
+
@course.started_on.day.should == 20
|
510
|
+
@course.started_on.year.should == 2006
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
it 'does not typecast non-date values' do
|
515
|
+
@course.started_on = 'not-date'
|
516
|
+
@course['started_on'].should eql('not-date')
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
describe 'when type primitive is a Time' do
|
521
|
+
describe 'and value given as a hash with keys like :year, :month, etc' do
|
522
|
+
it 'builds a Time instance from hash values' do
|
523
|
+
@course.ends_at = {
|
524
|
+
:year => '2006',
|
525
|
+
:month => '11',
|
526
|
+
:day => '23',
|
527
|
+
:hour => '12',
|
528
|
+
:min => '0',
|
529
|
+
:sec => '0'
|
530
|
+
}
|
531
|
+
result = @course['ends_at']
|
532
|
+
|
533
|
+
result.should be_kind_of(Time)
|
534
|
+
result.year.should eql(2006)
|
535
|
+
result.month.should eql(11)
|
536
|
+
result.day.should eql(23)
|
537
|
+
result.hour.should eql(12)
|
538
|
+
result.min.should eql(0)
|
539
|
+
result.sec.should eql(0)
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
describe 'and value is a string' do
|
544
|
+
it 'parses the string' do
|
545
|
+
t = Time.now
|
546
|
+
@course.ends_at = t.strftime('%Y/%m/%d %H:%M:%S %z')
|
547
|
+
@course['ends_at'].year.should eql(t.year)
|
548
|
+
@course['ends_at'].month.should eql(t.month)
|
549
|
+
@course['ends_at'].day.should eql(t.day)
|
550
|
+
@course['ends_at'].hour.should eql(t.hour)
|
551
|
+
@course['ends_at'].min.should eql(t.min)
|
552
|
+
@course['ends_at'].sec.should eql(t.sec)
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
it 'does not typecast non-time values' do
|
557
|
+
@course.ends_at = 'not-time'
|
558
|
+
@course['ends_at'].should eql('not-time')
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
describe 'when type primitive is a Class' do
|
563
|
+
it 'returns same value if a class' do
|
564
|
+
value = Course
|
565
|
+
@course.klass = value
|
566
|
+
@course['klass'].should equal(value)
|
567
|
+
end
|
568
|
+
|
569
|
+
it 'returns the class if found' do
|
570
|
+
@course.klass = 'Course'
|
571
|
+
@course['klass'].should eql(Course)
|
572
|
+
end
|
573
|
+
|
574
|
+
it 'does not typecast non-class values' do
|
575
|
+
@course.klass = 'NoClass'
|
576
|
+
@course['klass'].should eql('NoClass')
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
describe 'when type primitive is a Boolean' do
|
581
|
+
[ true, 'true', 'TRUE', '1', 1, 't', 'T' ].each do |value|
|
582
|
+
it "returns true when value is #{value.inspect}" do
|
583
|
+
@course.active = value
|
584
|
+
@course['active'].should be_true
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
[ false, 'false', 'FALSE', '0', 0, 'f', 'F' ].each do |value|
|
589
|
+
it "returns false when value is #{value.inspect}" do
|
590
|
+
@course.active = value
|
591
|
+
@course['active'].should be_false
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
[ 'string', 2, 1.0, BigDecimal('1.0'), DateTime.now, Time.now, Date.today, Class, Object.new, ].each do |value|
|
596
|
+
it "does not typecast value #{value.inspect}" do
|
597
|
+
@course.active = value
|
598
|
+
@course['active'].should equal(value)
|
599
|
+
end
|
600
|
+
end
|
262
601
|
end
|
263
602
|
end
|
264
603
|
end
|
@@ -286,4 +625,4 @@ describe "a casted model retrieved from the database" do
|
|
286
625
|
@cat.toys[1].casted_by.should === @cat
|
287
626
|
end
|
288
627
|
end
|
289
|
-
end
|
628
|
+
end
|