dm-core 0.10.0 → 0.10.1
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/History.txt +25 -5
- data/Manifest.txt +1 -0
- data/README.txt +67 -23
- data/Rakefile +0 -2
- data/deps.rip +1 -1
- data/dm-core.gemspec +6 -6
- data/lib/dm-core/adapters/abstract_adapter.rb +3 -76
- data/lib/dm-core/adapters/data_objects_adapter.rb +8 -39
- data/lib/dm-core/associations/many_to_many.rb +28 -16
- data/lib/dm-core/associations/many_to_one.rb +1 -45
- data/lib/dm-core/associations/one_to_many.rb +1 -38
- data/lib/dm-core/associations/relationship.rb +43 -20
- data/lib/dm-core/collection.rb +33 -32
- data/lib/dm-core/model/property.rb +8 -8
- data/lib/dm-core/model/relationship.rb +10 -12
- data/lib/dm-core/property.rb +20 -85
- data/lib/dm-core/property_set.rb +8 -8
- data/lib/dm-core/query/conditions/comparison.rb +13 -71
- data/lib/dm-core/query/conditions/operation.rb +73 -47
- data/lib/dm-core/query/operator.rb +3 -45
- data/lib/dm-core/query/path.rb +5 -41
- data/lib/dm-core/query.rb +37 -108
- data/lib/dm-core/repository.rb +3 -79
- data/lib/dm-core/resource.rb +54 -49
- data/lib/dm-core/support/chainable.rb +0 -2
- data/lib/dm-core/support/equalizer.rb +23 -0
- data/lib/dm-core/types/object.rb +4 -4
- data/lib/dm-core/version.rb +1 -1
- data/lib/dm-core.rb +3 -11
- data/spec/public/model/relationship_spec.rb +4 -4
- data/spec/public/property_spec.rb +5 -449
- data/spec/public/sel_spec.rb +52 -2
- data/spec/public/shared/collection_shared_spec.rb +79 -26
- data/spec/public/shared/finder_shared_spec.rb +6 -6
- data/spec/public/shared/resource_shared_spec.rb +2 -2
- data/spec/semipublic/property_spec.rb +524 -9
- data/spec/semipublic/query_spec.rb +6 -6
- data/tasks/hoe.rb +2 -2
- metadata +24 -4
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
3
3
|
|
4
|
+
# instance methods
|
4
5
|
describe DataMapper::Property do
|
5
6
|
|
6
7
|
# define the model prior to supported_by
|
@@ -21,19 +22,8 @@ describe DataMapper::Property do
|
|
21
22
|
property :md5hash, String, :key => true, :length => 32
|
22
23
|
property :title, String, :nullable => false, :unique => true
|
23
24
|
property :description, Text, :length => 1..1024, :lazy => [ :detail ]
|
24
|
-
|
25
25
|
property :format, String, :default => 'jpeg'
|
26
|
-
|
27
|
-
property :size, Object
|
28
|
-
property :filesize, Float
|
29
|
-
property :width, Integer
|
30
|
-
property :quality, BigDecimal
|
31
|
-
|
32
|
-
property :taken_on, Date
|
33
|
-
property :taken_at, Time, :default => lambda { |resource, property| Time.now }
|
34
|
-
property :retouched_at, DateTime
|
35
|
-
property :type, Class
|
36
|
-
property :visible, Boolean, :default => true
|
26
|
+
property :taken_at, Time, :default => proc { Time.now }
|
37
27
|
end
|
38
28
|
end
|
39
29
|
|
@@ -335,10 +325,9 @@ describe DataMapper::Property do
|
|
335
325
|
it 'triggers lazy loading for given resource'
|
336
326
|
|
337
327
|
it 'type casts given value' do
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
@image.title.should == '1.0'
|
328
|
+
@property.set(@image, Addressable::URI.parse('http://test.example/'))
|
329
|
+
# get a string that has been typecasted using #to_str
|
330
|
+
@image.title.should == 'http://test.example/'
|
342
331
|
end
|
343
332
|
|
344
333
|
it 'stores original value' do
|
@@ -367,413 +356,6 @@ describe DataMapper::Property do
|
|
367
356
|
end
|
368
357
|
end
|
369
358
|
|
370
|
-
describe '#typecast' do
|
371
|
-
describe "when type is able to do typecasting on it's own" do
|
372
|
-
it 'delegates all the work to the type'
|
373
|
-
end
|
374
|
-
|
375
|
-
describe 'when value is nil' do
|
376
|
-
it 'returns value unchanged' do
|
377
|
-
Image.properties[:size].typecast(nil).should be(nil)
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
describe 'when value is a Ruby primitive' do
|
382
|
-
it 'returns value unchanged' do
|
383
|
-
Image.properties[:size].typecast([3200, 2400]).should == [3200, 2400]
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
describe 'when type primitive is a String' do
|
388
|
-
before :all do
|
389
|
-
@property = Image.properties[:title]
|
390
|
-
end
|
391
|
-
|
392
|
-
it 'returns same value if a string' do
|
393
|
-
@value = '1.0'
|
394
|
-
@property.typecast(@value).should equal(@value)
|
395
|
-
end
|
396
|
-
|
397
|
-
it 'returns string representation of the new value' do
|
398
|
-
@property.typecast(1.0).should eql('1.0')
|
399
|
-
end
|
400
|
-
end
|
401
|
-
|
402
|
-
describe 'when type primitive is a Float' do
|
403
|
-
before :all do
|
404
|
-
@property = Image.properties[:filesize]
|
405
|
-
end
|
406
|
-
|
407
|
-
it 'returns same value if a float' do
|
408
|
-
@value = 24.0
|
409
|
-
@property.typecast(@value).should equal(@value)
|
410
|
-
end
|
411
|
-
|
412
|
-
it 'returns float representation of a zero string integer' do
|
413
|
-
@property.typecast('0').should eql(0.0)
|
414
|
-
end
|
415
|
-
|
416
|
-
it 'returns float representation of a positive string integer' do
|
417
|
-
@property.typecast('24').should eql(24.0)
|
418
|
-
end
|
419
|
-
|
420
|
-
it 'returns float representation of a negative string integer' do
|
421
|
-
@property.typecast('-24').should eql(-24.0)
|
422
|
-
end
|
423
|
-
|
424
|
-
it 'returns float representation of a zero string float' do
|
425
|
-
@property.typecast('0.0').should eql(0.0)
|
426
|
-
end
|
427
|
-
|
428
|
-
it 'returns float representation of a positive string float' do
|
429
|
-
@property.typecast('24.35').should eql(24.35)
|
430
|
-
end
|
431
|
-
|
432
|
-
it 'returns float representation of a negative string float' do
|
433
|
-
@property.typecast('-24.35').should eql(-24.35)
|
434
|
-
end
|
435
|
-
|
436
|
-
it 'returns float representation of a zero string float, with no leading digits' do
|
437
|
-
@property.typecast('.0').should eql(0.0)
|
438
|
-
end
|
439
|
-
|
440
|
-
it 'returns float representation of a positive string float, with no leading digits' do
|
441
|
-
@property.typecast('.41').should eql(0.41)
|
442
|
-
end
|
443
|
-
|
444
|
-
it 'returns float representation of a zero integer' do
|
445
|
-
@property.typecast(0).should eql(0.0)
|
446
|
-
end
|
447
|
-
|
448
|
-
it 'returns float representation of a positive integer' do
|
449
|
-
@property.typecast(24).should eql(24.0)
|
450
|
-
end
|
451
|
-
|
452
|
-
it 'returns float representation of a negative integer' do
|
453
|
-
@property.typecast(-24).should eql(-24.0)
|
454
|
-
end
|
455
|
-
|
456
|
-
it 'returns float representation of a zero decimal' do
|
457
|
-
@property.typecast(BigDecimal('0.0')).should eql(0.0)
|
458
|
-
end
|
459
|
-
|
460
|
-
it 'returns float representation of a positive decimal' do
|
461
|
-
@property.typecast(BigDecimal('24.35')).should eql(24.35)
|
462
|
-
end
|
463
|
-
|
464
|
-
it 'returns float representation of a negative decimal' do
|
465
|
-
@property.typecast(BigDecimal('-24.35')).should eql(-24.35)
|
466
|
-
end
|
467
|
-
|
468
|
-
[ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |value|
|
469
|
-
it "does not typecast non-numeric value #{value.inspect}" do
|
470
|
-
@property.typecast(value).should equal(value)
|
471
|
-
end
|
472
|
-
end
|
473
|
-
end
|
474
|
-
|
475
|
-
describe 'when type primitive is a Integer' do
|
476
|
-
before :all do
|
477
|
-
@property = Image.properties[:width]
|
478
|
-
end
|
479
|
-
|
480
|
-
it 'returns same value if an integer' do
|
481
|
-
@value = 24
|
482
|
-
@property.typecast(@value).should equal(@value)
|
483
|
-
end
|
484
|
-
|
485
|
-
it 'returns integer representation of a zero string integer' do
|
486
|
-
@property.typecast('0').should eql(0)
|
487
|
-
end
|
488
|
-
|
489
|
-
it 'returns integer representation of a positive string integer' do
|
490
|
-
@property.typecast('24').should eql(24)
|
491
|
-
end
|
492
|
-
|
493
|
-
it 'returns integer representation of a negative string integer' do
|
494
|
-
@property.typecast('-24').should eql(-24)
|
495
|
-
end
|
496
|
-
|
497
|
-
it 'returns integer representation of a zero string float' do
|
498
|
-
@property.typecast('0.0').should eql(0)
|
499
|
-
end
|
500
|
-
|
501
|
-
it 'returns integer representation of a positive string float' do
|
502
|
-
@property.typecast('24.35').should eql(24)
|
503
|
-
end
|
504
|
-
|
505
|
-
it 'returns integer representation of a negative string float' do
|
506
|
-
@property.typecast('-24.35').should eql(-24)
|
507
|
-
end
|
508
|
-
|
509
|
-
it 'returns integer representation of a zero string float, with no leading digits' do
|
510
|
-
@property.typecast('.0').should eql(0)
|
511
|
-
end
|
512
|
-
|
513
|
-
it 'returns integer representation of a positive string float, with no leading digits' do
|
514
|
-
@property.typecast('.41').should eql(0)
|
515
|
-
end
|
516
|
-
|
517
|
-
it 'returns integer representation of a zero float' do
|
518
|
-
@property.typecast(0.0).should eql(0)
|
519
|
-
end
|
520
|
-
|
521
|
-
it 'returns integer representation of a positive float' do
|
522
|
-
@property.typecast(24.35).should eql(24)
|
523
|
-
end
|
524
|
-
|
525
|
-
it 'returns integer representation of a negative float' do
|
526
|
-
@property.typecast(-24.35).should eql(-24)
|
527
|
-
end
|
528
|
-
|
529
|
-
it 'returns integer representation of a zero decimal' do
|
530
|
-
@property.typecast(BigDecimal('0.0')).should eql(0)
|
531
|
-
end
|
532
|
-
|
533
|
-
it 'returns integer representation of a positive decimal' do
|
534
|
-
@property.typecast(BigDecimal('24.35')).should eql(24)
|
535
|
-
end
|
536
|
-
|
537
|
-
it 'returns integer representation of a negative decimal' do
|
538
|
-
@property.typecast(BigDecimal('-24.35')).should eql(-24)
|
539
|
-
end
|
540
|
-
|
541
|
-
[ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |value|
|
542
|
-
it "does not typecast non-numeric value #{value.inspect}" do
|
543
|
-
@property.typecast(value).should equal(value)
|
544
|
-
end
|
545
|
-
end
|
546
|
-
end
|
547
|
-
|
548
|
-
describe 'when type primitive is a BigDecimal' do
|
549
|
-
before :all do
|
550
|
-
@property = Image.properties[:quality]
|
551
|
-
end
|
552
|
-
|
553
|
-
it 'returns same value if a decimal' do
|
554
|
-
@value = BigDecimal('24.0')
|
555
|
-
@property.typecast(@value).should equal(@value)
|
556
|
-
end
|
557
|
-
|
558
|
-
it 'returns decimal representation of a zero string integer' do
|
559
|
-
@property.typecast('0').should eql(BigDecimal('0.0'))
|
560
|
-
end
|
561
|
-
|
562
|
-
it 'returns decimal representation of a positive string integer' do
|
563
|
-
@property.typecast('24').should eql(BigDecimal('24.0'))
|
564
|
-
end
|
565
|
-
|
566
|
-
it 'returns decimal representation of a negative string integer' do
|
567
|
-
@property.typecast('-24').should eql(BigDecimal('-24.0'))
|
568
|
-
end
|
569
|
-
|
570
|
-
it 'returns decimal representation of a zero string float' do
|
571
|
-
@property.typecast('0.0').should eql(BigDecimal('0.0'))
|
572
|
-
end
|
573
|
-
|
574
|
-
it 'returns decimal representation of a positive string float' do
|
575
|
-
@property.typecast('24.35').should eql(BigDecimal('24.35'))
|
576
|
-
end
|
577
|
-
|
578
|
-
it 'returns decimal representation of a negative string float' do
|
579
|
-
@property.typecast('-24.35').should eql(BigDecimal('-24.35'))
|
580
|
-
end
|
581
|
-
|
582
|
-
it 'returns decimal representation of a zero string float, with no leading digits' do
|
583
|
-
@property.typecast('.0').should eql(BigDecimal('0.0'))
|
584
|
-
end
|
585
|
-
|
586
|
-
it 'returns decimal representation of a positive string float, with no leading digits' do
|
587
|
-
@property.typecast('.41').should eql(BigDecimal('0.41'))
|
588
|
-
end
|
589
|
-
|
590
|
-
it 'returns decimal representation of a zero integer' do
|
591
|
-
@property.typecast(0).should eql(BigDecimal('0.0'))
|
592
|
-
end
|
593
|
-
|
594
|
-
it 'returns decimal representation of a positive integer' do
|
595
|
-
@property.typecast(24).should eql(BigDecimal('24.0'))
|
596
|
-
end
|
597
|
-
|
598
|
-
it 'returns decimal representation of a negative integer' do
|
599
|
-
@property.typecast(-24).should eql(BigDecimal('-24.0'))
|
600
|
-
end
|
601
|
-
|
602
|
-
it 'returns decimal representation of a zero float' do
|
603
|
-
@property.typecast(0.0).should eql(BigDecimal('0.0'))
|
604
|
-
end
|
605
|
-
|
606
|
-
it 'returns decimal representation of a positive float' do
|
607
|
-
@property.typecast(24.35).should eql(BigDecimal('24.35'))
|
608
|
-
end
|
609
|
-
|
610
|
-
it 'returns decimal representation of a negative float' do
|
611
|
-
@property.typecast(-24.35).should eql(BigDecimal('-24.35'))
|
612
|
-
end
|
613
|
-
|
614
|
-
[ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |value|
|
615
|
-
it "does not typecast non-numeric value #{value.inspect}" do
|
616
|
-
@property.typecast(value).should equal(value)
|
617
|
-
end
|
618
|
-
end
|
619
|
-
end
|
620
|
-
|
621
|
-
describe 'when type primitive is a DateTime' do
|
622
|
-
before do
|
623
|
-
@property = Image.properties[:retouched_at]
|
624
|
-
end
|
625
|
-
|
626
|
-
describe 'and value given as a hash with keys like :year, :month, etc' do
|
627
|
-
it 'builds a DateTime instance from hash values' do
|
628
|
-
result = @property.typecast(
|
629
|
-
'year' => '2006',
|
630
|
-
'month' => '11',
|
631
|
-
'day' => '23',
|
632
|
-
'hour' => '12',
|
633
|
-
'min' => '0',
|
634
|
-
'sec' => '0'
|
635
|
-
)
|
636
|
-
|
637
|
-
result.should be_kind_of(DateTime)
|
638
|
-
result.year.should eql(2006)
|
639
|
-
result.month.should eql(11)
|
640
|
-
result.day.should eql(23)
|
641
|
-
result.hour.should eql(12)
|
642
|
-
result.min.should eql(0)
|
643
|
-
result.sec.should eql(0)
|
644
|
-
end
|
645
|
-
end
|
646
|
-
|
647
|
-
describe 'and value is a string' do
|
648
|
-
it 'parses the string' do
|
649
|
-
Image.properties[:retouched_at].typecast('Dec, 2006').month.should == 12
|
650
|
-
end
|
651
|
-
end
|
652
|
-
|
653
|
-
it 'does not typecast non-datetime values' do
|
654
|
-
@property.typecast('not-datetime').should eql('not-datetime')
|
655
|
-
end
|
656
|
-
end
|
657
|
-
|
658
|
-
describe 'when type primitive is a Date' do
|
659
|
-
before do
|
660
|
-
@property = Image.properties[:taken_on]
|
661
|
-
end
|
662
|
-
|
663
|
-
describe 'and value given as a hash with keys like :year, :month, etc' do
|
664
|
-
it 'builds a Date instance from hash values' do
|
665
|
-
result = @property.typecast(
|
666
|
-
'year' => '2007',
|
667
|
-
'month' => '3',
|
668
|
-
'day' => '25'
|
669
|
-
)
|
670
|
-
|
671
|
-
result.should be_kind_of(Date)
|
672
|
-
result.year.should eql(2007)
|
673
|
-
result.month.should eql(3)
|
674
|
-
result.day.should eql(25)
|
675
|
-
end
|
676
|
-
end
|
677
|
-
|
678
|
-
describe 'and value is a string' do
|
679
|
-
it 'parses the string' do
|
680
|
-
result = @property.typecast('Dec 20th, 2006')
|
681
|
-
result.month.should == 12
|
682
|
-
result.day.should == 20
|
683
|
-
result.year.should == 2006
|
684
|
-
end
|
685
|
-
end
|
686
|
-
|
687
|
-
it 'does not typecast non-date values' do
|
688
|
-
@property.typecast('not-date').should eql('not-date')
|
689
|
-
end
|
690
|
-
end
|
691
|
-
|
692
|
-
describe 'when type primitive is a Time' do
|
693
|
-
before do
|
694
|
-
@property = Image.properties[:taken_at]
|
695
|
-
end
|
696
|
-
|
697
|
-
describe 'and value given as a hash with keys like :year, :month, etc' do
|
698
|
-
it 'builds a Time instance from hash values' do
|
699
|
-
result = @property.typecast(
|
700
|
-
'year' => '2006',
|
701
|
-
'month' => '11',
|
702
|
-
'day' => '23',
|
703
|
-
'hour' => '12',
|
704
|
-
'min' => '0',
|
705
|
-
'sec' => '0'
|
706
|
-
)
|
707
|
-
|
708
|
-
result.should be_kind_of(Time)
|
709
|
-
result.year.should eql(2006)
|
710
|
-
result.month.should eql(11)
|
711
|
-
result.day.should eql(23)
|
712
|
-
result.hour.should eql(12)
|
713
|
-
result.min.should eql(0)
|
714
|
-
result.sec.should eql(0)
|
715
|
-
end
|
716
|
-
end
|
717
|
-
|
718
|
-
describe 'and value is a string' do
|
719
|
-
it 'parses the string' do
|
720
|
-
result = @property.typecast('22:24')
|
721
|
-
result.hour.should eql(22)
|
722
|
-
result.min.should eql(24)
|
723
|
-
end
|
724
|
-
end
|
725
|
-
|
726
|
-
it 'does not typecast non-time values' do
|
727
|
-
pending 'Time#parse is too permissive' do
|
728
|
-
@property.typecast('not-time').should eql('not-time')
|
729
|
-
end
|
730
|
-
end
|
731
|
-
end
|
732
|
-
|
733
|
-
describe 'when type primitive is a Class' do
|
734
|
-
before do
|
735
|
-
@property = Image.properties[:type]
|
736
|
-
end
|
737
|
-
|
738
|
-
it 'returns same value if a class' do
|
739
|
-
@value = Image
|
740
|
-
@property.typecast(@value).should equal(@value)
|
741
|
-
end
|
742
|
-
|
743
|
-
it 'returns the class if found' do
|
744
|
-
@property.typecast('Image').should eql(Image)
|
745
|
-
end
|
746
|
-
|
747
|
-
it 'does not typecast non-class values' do
|
748
|
-
@property.typecast('NoClass').should eql('NoClass')
|
749
|
-
end
|
750
|
-
end
|
751
|
-
|
752
|
-
describe 'when type primitive is a Boolean' do
|
753
|
-
before do
|
754
|
-
@property = Image.properties[:visible]
|
755
|
-
end
|
756
|
-
|
757
|
-
[ true, 'true', 'TRUE', '1', 1, 't', 'T' ].each do |value|
|
758
|
-
it "returns true when value is #{value.inspect}" do
|
759
|
-
@property.typecast(value).should be_true
|
760
|
-
end
|
761
|
-
end
|
762
|
-
|
763
|
-
[ false, 'false', 'FALSE', '0', 0, 'f', 'F' ].each do |value|
|
764
|
-
it "returns false when value is #{value.inspect}" do
|
765
|
-
@property.typecast(value).should be_false
|
766
|
-
end
|
767
|
-
end
|
768
|
-
|
769
|
-
[ 'string', 2, 1.0, BigDecimal('1.0'), DateTime.now, Time.now, Date.today, Class, Object.new, ].each do |value|
|
770
|
-
it "does not typecast value #{value.inspect}" do
|
771
|
-
@property.typecast(value).should equal(value)
|
772
|
-
end
|
773
|
-
end
|
774
|
-
end
|
775
|
-
end # #typecase
|
776
|
-
|
777
359
|
describe '#unique?' do
|
778
360
|
it 'is true for fields that explicitly given uniq index' do
|
779
361
|
Track.properties[:musicbrainz_hash].unique?.should be_true
|
@@ -799,31 +381,5 @@ describe DataMapper::Property do
|
|
799
381
|
Image.properties[:title].unique_index.should be_nil
|
800
382
|
end
|
801
383
|
end
|
802
|
-
|
803
|
-
describe '#valid?' do
|
804
|
-
describe 'when type primitive is a Boolean' do
|
805
|
-
before do
|
806
|
-
@property = Image.properties[:visible]
|
807
|
-
end
|
808
|
-
|
809
|
-
[ true, false ].each do |value|
|
810
|
-
it "returns true when value is #{value.inspect}" do
|
811
|
-
@property.valid?(value).should be_true
|
812
|
-
end
|
813
|
-
end
|
814
|
-
|
815
|
-
[ 'true', 'TRUE', '1', 1, 't', 'T', 'false', 'FALSE', '0', 0, 'f', 'F' ].each do |value|
|
816
|
-
it "returns false for #{value.inspect}" do
|
817
|
-
@property.valid?(value).should be_false
|
818
|
-
end
|
819
|
-
end
|
820
|
-
end
|
821
|
-
end
|
822
|
-
|
823
|
-
describe '#value' do
|
824
|
-
it 'returns value for core types'
|
825
|
-
|
826
|
-
it 'triggers dump operation for custom types'
|
827
|
-
end
|
828
384
|
end
|
829
385
|
end # DataMapper::Property
|
data/spec/public/sel_spec.rb
CHANGED
@@ -15,8 +15,8 @@ describe 'SEL', 'with different key types' do
|
|
15
15
|
class Article
|
16
16
|
include DataMapper::Resource
|
17
17
|
|
18
|
-
property :id,
|
19
|
-
property :title,
|
18
|
+
property :id, Serial
|
19
|
+
property :title, String, :nullable => false
|
20
20
|
|
21
21
|
property :author_id, String # different type
|
22
22
|
|
@@ -42,3 +42,53 @@ describe 'SEL', 'with different key types' do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
describe 'SEL', 'with STI subclasses' do
|
47
|
+
before :all do
|
48
|
+
module ::Blog
|
49
|
+
class Author
|
50
|
+
include DataMapper::Resource
|
51
|
+
|
52
|
+
property :id, Serial
|
53
|
+
property :name, String
|
54
|
+
|
55
|
+
has n, :messages
|
56
|
+
end
|
57
|
+
|
58
|
+
class Message
|
59
|
+
include DataMapper::Resource
|
60
|
+
|
61
|
+
property :id, Serial
|
62
|
+
property :type, Discriminator
|
63
|
+
property :title, String, :nullable => false
|
64
|
+
|
65
|
+
belongs_to :author
|
66
|
+
end
|
67
|
+
|
68
|
+
class Article < Message; end
|
69
|
+
class Comment < Message; end
|
70
|
+
end
|
71
|
+
|
72
|
+
@author_model = Blog::Author
|
73
|
+
@message_model = Blog::Message
|
74
|
+
@article_model = Blog::Article
|
75
|
+
@comment_model = Blog::Comment
|
76
|
+
end
|
77
|
+
|
78
|
+
supported_by :all do
|
79
|
+
before :all do
|
80
|
+
author1 = @author_model.create(:name => 'Dan Kubb')
|
81
|
+
author2 = @author_model.create(:name => 'Sindre Aarsaether')
|
82
|
+
|
83
|
+
@article_model.create(:title => 'SEL', :author => author1)
|
84
|
+
@article_model.create(:title => 'STI', :author => author1)
|
85
|
+
@comment_model.create(:title => 'SEL and STI error', :author => author2)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should allow STI loading of mixed relationships' do
|
89
|
+
lambda {
|
90
|
+
@message_model.all.each { |message| message.author }
|
91
|
+
}.should_not raise_error(ArgumentError)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -618,24 +618,52 @@ share_examples_for 'A public Collection' do
|
|
618
618
|
describe '#pop' do
|
619
619
|
before :all do
|
620
620
|
@new = @articles.create(:title => 'Sample Article') # TODO: freeze @new
|
621
|
-
|
622
|
-
@return = @resource = @articles.pop
|
623
621
|
end
|
624
622
|
|
625
|
-
|
626
|
-
|
627
|
-
|
623
|
+
describe 'with no arguments' do
|
624
|
+
before :all do
|
625
|
+
@return = @articles.pop
|
626
|
+
end
|
628
627
|
|
629
|
-
|
630
|
-
|
631
|
-
|
628
|
+
it 'should return a Resource' do
|
629
|
+
@return.should be_kind_of(DataMapper::Resource)
|
630
|
+
end
|
631
|
+
|
632
|
+
it 'should be the last Resource in the Collection' do
|
633
|
+
@return.should == @new
|
634
|
+
end
|
632
635
|
|
633
|
-
|
634
|
-
|
636
|
+
it 'should remove the Resource from the Collection' do
|
637
|
+
@articles.should_not be_include(@new)
|
638
|
+
end
|
639
|
+
|
640
|
+
it 'should orphan the Resource' do
|
641
|
+
@return.collection.should_not equal(@articles)
|
642
|
+
end
|
635
643
|
end
|
636
644
|
|
637
|
-
|
638
|
-
|
645
|
+
if RUBY_VERSION >= '1.8.7'
|
646
|
+
describe 'with a limit specified' do
|
647
|
+
before :all do
|
648
|
+
@return = @articles.pop(1)
|
649
|
+
end
|
650
|
+
|
651
|
+
it 'should return an Array' do
|
652
|
+
@return.should be_kind_of(Array)
|
653
|
+
end
|
654
|
+
|
655
|
+
it 'should return the expected Resources' do
|
656
|
+
@return.should == [ @new ]
|
657
|
+
end
|
658
|
+
|
659
|
+
it 'should remove the Resource from the Collection' do
|
660
|
+
@articles.should_not be_include(@new)
|
661
|
+
end
|
662
|
+
|
663
|
+
it 'should orphan the Resource' do
|
664
|
+
@return.each { |resource| resource.collection.should_not equal(@articles) }
|
665
|
+
end
|
666
|
+
end
|
639
667
|
end
|
640
668
|
end
|
641
669
|
|
@@ -941,26 +969,51 @@ share_examples_for 'A public Collection' do
|
|
941
969
|
it { @articles.should respond_to(:shift) }
|
942
970
|
|
943
971
|
describe '#shift' do
|
944
|
-
|
945
|
-
|
972
|
+
describe 'with no arguments' do
|
973
|
+
before :all do
|
974
|
+
@return = @articles.shift
|
975
|
+
end
|
946
976
|
|
947
|
-
|
948
|
-
|
977
|
+
it 'should return a Resource' do
|
978
|
+
@return.should be_kind_of(DataMapper::Resource)
|
979
|
+
end
|
949
980
|
|
950
|
-
|
951
|
-
|
952
|
-
|
981
|
+
it 'should be the first Resource in the Collection' do
|
982
|
+
@return.key.should == @article.key
|
983
|
+
end
|
953
984
|
|
954
|
-
|
955
|
-
|
956
|
-
|
985
|
+
it 'should remove the Resource from the Collection' do
|
986
|
+
@articles.should_not be_include(@return)
|
987
|
+
end
|
957
988
|
|
958
|
-
|
959
|
-
|
989
|
+
it 'should orphan the Resource' do
|
990
|
+
@return.collection.should_not equal(@articles)
|
991
|
+
end
|
960
992
|
end
|
961
993
|
|
962
|
-
|
963
|
-
|
994
|
+
if RUBY_VERSION >= '1.8.7'
|
995
|
+
describe 'with a limit specified' do
|
996
|
+
before :all do
|
997
|
+
@return = @articles.shift(1)
|
998
|
+
end
|
999
|
+
|
1000
|
+
it 'should return an Array' do
|
1001
|
+
@return.should be_kind_of(Array)
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
it 'should return the expected Resources' do
|
1005
|
+
@return.size.should == 1
|
1006
|
+
@return.first.key.should == @article.key
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
it 'should remove the Resource from the Collection' do
|
1010
|
+
@articles.should_not be_include(@article)
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
it 'should orphan the Resource' do
|
1014
|
+
@return.each { |resource| resource.collection.should_not equal(@articles) }
|
1015
|
+
end
|
1016
|
+
end
|
964
1017
|
end
|
965
1018
|
end
|
966
1019
|
|