dm-core 1.0.0.rc2 → 1.0.0.rc3

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 (65) hide show
  1. data/Gemfile +1 -1
  2. data/LICENSE +1 -1
  3. data/README.rdoc +1 -1
  4. data/Rakefile +3 -4
  5. data/VERSION +1 -1
  6. data/dm-core.gemspec +7 -5
  7. data/lib/dm-core.rb +44 -0
  8. data/lib/dm-core/adapters.rb +1 -1
  9. data/lib/dm-core/adapters/abstract_adapter.rb +16 -0
  10. data/lib/dm-core/collection.rb +2 -2
  11. data/lib/dm-core/model.rb +64 -53
  12. data/lib/dm-core/model/property.rb +14 -6
  13. data/lib/dm-core/model/relationship.rb +10 -18
  14. data/lib/dm-core/property.rb +10 -10
  15. data/lib/dm-core/query.rb +8 -18
  16. data/lib/dm-core/resource.rb +3 -11
  17. data/lib/dm-core/resource/state.rb +13 -16
  18. data/lib/dm-core/resource/state/dirty.rb +11 -1
  19. data/lib/dm-core/resource/state/transient.rb +9 -1
  20. data/lib/dm-core/spec/lib/adapter_helpers.rb +5 -0
  21. data/lib/dm-core/spec/shared/adapter_spec.rb +2 -0
  22. data/lib/dm-core/spec/shared/resource_spec.rb +0 -31
  23. data/lib/dm-core/version.rb +1 -1
  24. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +2 -0
  25. data/spec/public/associations/many_to_many_spec.rb +2 -1
  26. data/spec/public/associations/many_to_one_spec.rb +1 -0
  27. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +1 -0
  28. data/spec/public/associations/one_to_many_spec.rb +2 -0
  29. data/spec/public/associations/one_to_one_spec.rb +2 -0
  30. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +1 -0
  31. data/spec/public/collection_spec.rb +2 -0
  32. data/spec/public/finalize_spec.rb +34 -0
  33. data/spec/public/model/hook_spec.rb +1 -0
  34. data/spec/public/model/property_spec.rb +1 -0
  35. data/spec/public/model/relationship_spec.rb +22 -0
  36. data/spec/public/model_spec.rb +138 -3
  37. data/spec/public/property/discriminator_spec.rb +1 -0
  38. data/spec/public/property/object_spec.rb +1 -0
  39. data/spec/public/property_spec.rb +13 -4
  40. data/spec/public/resource_spec.rb +1 -0
  41. data/spec/public/sel_spec.rb +2 -0
  42. data/spec/public/shared/collection_shared_spec.rb +0 -45
  43. data/spec/public/shared/finder_shared_spec.rb +110 -0
  44. data/spec/public/shared/property_shared_spec.rb +1 -1
  45. data/spec/rcov.opts +1 -1
  46. data/spec/semipublic/associations/many_to_many_spec.rb +3 -0
  47. data/spec/semipublic/associations/many_to_one_spec.rb +2 -0
  48. data/spec/semipublic/associations/one_to_many_spec.rb +2 -0
  49. data/spec/semipublic/associations/one_to_one_spec.rb +2 -0
  50. data/spec/semipublic/associations/relationship_spec.rb +6 -0
  51. data/spec/semipublic/query/conditions/comparison_spec.rb +3 -0
  52. data/spec/semipublic/query/conditions/operation_spec.rb +1 -0
  53. data/spec/semipublic/query/path_spec.rb +2 -0
  54. data/spec/semipublic/query_spec.rb +2 -3
  55. data/spec/semipublic/resource/state/clean_spec.rb +2 -1
  56. data/spec/semipublic/resource/state/deleted_spec.rb +2 -1
  57. data/spec/semipublic/resource/state/dirty_spec.rb +42 -20
  58. data/spec/semipublic/resource/state/immutable_spec.rb +7 -1
  59. data/spec/semipublic/resource/state/transient_spec.rb +69 -40
  60. data/spec/semipublic/resource/state_spec.rb +72 -66
  61. data/spec/semipublic/shared/property_shared_spec.rb +1 -0
  62. data/spec/semipublic/shared/resource_shared_spec.rb +1 -0
  63. data/spec/spec_helper.rb +0 -10
  64. data/tasks/spec.rake +3 -0
  65. metadata +9 -7
@@ -8,6 +8,7 @@ describe DataMapper::Model::Property do
8
8
 
9
9
  property :id, Serial
10
10
  end
11
+ DataMapper.finalize
11
12
  end
12
13
 
13
14
  describe '#property' do
@@ -468,6 +468,7 @@ describe DataMapper::Associations do
468
468
 
469
469
  Car.belongs_to(@name, :required => false)
470
470
  Engine.has(1, :car)
471
+ DataMapper.finalize
471
472
  end
472
473
 
473
474
  supported_by :all do
@@ -486,6 +487,7 @@ describe DataMapper::Associations do
486
487
  describe 'with a :key option' do
487
488
  before :all do
488
489
  @relationship = Car.belongs_to("#{@name}_with_key".to_sym, @model, :required => false, :key => true)
490
+ DataMapper.finalize
489
491
  end
490
492
 
491
493
  it 'should create a foreign key that is part of the key' do
@@ -501,6 +503,7 @@ describe DataMapper::Associations do
501
503
  before :all do
502
504
  Car.has(1, :engine)
503
505
  Engine.belongs_to(:car)
506
+ DataMapper.finalize
504
507
  end
505
508
 
506
509
  supported_by :all do
@@ -628,6 +631,7 @@ describe DataMapper::Associations do
628
631
  describe 'with a model' do
629
632
  before :all do
630
633
  Engine.belongs_to(:vehicle, Car)
634
+ DataMapper.finalize
631
635
  end
632
636
 
633
637
  it 'should set the relationship target model' do
@@ -638,6 +642,7 @@ describe DataMapper::Associations do
638
642
  describe 'with a :model option' do
639
643
  before :all do
640
644
  Engine.belongs_to(:vehicle, :model => Car)
645
+ DataMapper.finalize
641
646
  end
642
647
 
643
648
  it 'should set the relationship target model' do
@@ -648,6 +653,7 @@ describe DataMapper::Associations do
648
653
  describe 'with a single element as :child_key option' do
649
654
  before :all do
650
655
  Engine.belongs_to(:vehicle, :model => Car, :child_key => :bike_id)
656
+ DataMapper.finalize
651
657
  end
652
658
 
653
659
  it 'should set the relationship child key' do
@@ -658,6 +664,7 @@ describe DataMapper::Associations do
658
664
  describe 'with an array as :child_key option' do
659
665
  before :all do
660
666
  Engine.belongs_to(:vehicle, :model => Car, :child_key => [:bike_id])
667
+ DataMapper.finalize
661
668
  end
662
669
 
663
670
  it 'should set the relationship child key' do
@@ -668,6 +675,7 @@ describe DataMapper::Associations do
668
675
  describe 'with a single element as :parent_key option' do
669
676
  before :all do
670
677
  Engine.belongs_to(:vehicle, :model => Car, :parent_key => :name)
678
+ DataMapper.finalize
671
679
  end
672
680
 
673
681
  it 'should set the relationship parent key' do
@@ -678,6 +686,7 @@ describe DataMapper::Associations do
678
686
  describe 'with an array as :parent_key option' do
679
687
  before :all do
680
688
  Engine.belongs_to(:vehicle, :model => Car, :parent_key => [:name])
689
+ DataMapper.finalize
681
690
  end
682
691
 
683
692
  it 'should set the relationship parent key' do
@@ -696,6 +705,7 @@ describe DataMapper::Associations do
696
705
 
697
706
  Car.has(1, @name)
698
707
  Engine.belongs_to(:car)
708
+ DataMapper.finalize
699
709
  end
700
710
 
701
711
  supported_by :all do
@@ -720,6 +730,7 @@ describe DataMapper::Associations do
720
730
 
721
731
  Car.has(1, @name, :through => DataMapper::Resource)
722
732
  Engine.has(1, :car, :through => DataMapper::Resource)
733
+ DataMapper.finalize
723
734
  end
724
735
 
725
736
  supported_by :all do
@@ -753,6 +764,7 @@ describe DataMapper::Associations do
753
764
 
754
765
  Car.has(1..4, @name)
755
766
  Door.belongs_to(:car, :required => false)
767
+ DataMapper.finalize
756
768
  end
757
769
 
758
770
  supported_by :all do
@@ -777,6 +789,7 @@ describe DataMapper::Associations do
777
789
 
778
790
  Window.has(1, :car, :through => DataMapper::Resource)
779
791
  Car.has(1..4, :windows, :through => DataMapper::Resource)
792
+ DataMapper.finalize
780
793
  end
781
794
 
782
795
  supported_by :all do
@@ -806,6 +819,7 @@ describe DataMapper::Associations do
806
819
  describe 'when the 3rd argument is a Model' do
807
820
  before :all do
808
821
  Car.has(1, :engine, Engine)
822
+ DataMapper.finalize
809
823
  end
810
824
 
811
825
  it 'should set the relationship target model' do
@@ -816,6 +830,7 @@ describe DataMapper::Associations do
816
830
  describe 'when the 3rd argument is a String' do
817
831
  before :all do
818
832
  Car.has(1, :engine, 'Engine')
833
+ DataMapper.finalize
819
834
  end
820
835
 
821
836
  it 'should set the relationship target model' do
@@ -836,6 +851,7 @@ describe DataMapper::Associations do
836
851
  describe 'when a relationship has an inverse' do
837
852
  before :all do
838
853
  @engine_relationship = Car.has(1, :engine, :inverse => Engine.belongs_to(:sports_car, Car))
854
+ DataMapper.finalize
839
855
  end
840
856
 
841
857
  supported_by :all do
@@ -848,6 +864,7 @@ describe DataMapper::Associations do
848
864
  describe 'when a relationship does not have an inverse' do
849
865
  before :all do
850
866
  @engine_relationship = Car.has(1, :engine)
867
+ DataMapper.finalize
851
868
  end
852
869
 
853
870
  supported_by :all do
@@ -865,6 +882,7 @@ describe DataMapper::Associations do
865
882
  class ::ElectricCar < Car; end
866
883
 
867
884
  Car.has(1, :engine, :inverse => Engine.belongs_to(:sports_car, Car))
885
+ DataMapper.finalize
868
886
  end
869
887
 
870
888
  supported_by :all do
@@ -889,6 +907,7 @@ describe DataMapper::Associations do
889
907
  class ::ElectricCar < Car; end
890
908
 
891
909
  Car.has(1, :engine)
910
+ DataMapper.finalize
892
911
  end
893
912
 
894
913
  supported_by :all do
@@ -915,6 +934,7 @@ describe DataMapper::Associations do
915
934
  class ::ElectricCar < Car; end
916
935
 
917
936
  ElectricCar.has(1, :engine, :inverse => Engine.belongs_to(:sports_car, Car))
937
+ DataMapper.finalize
918
938
  end
919
939
 
920
940
  supported_by :all do
@@ -939,6 +959,7 @@ describe DataMapper::Associations do
939
959
  class ::ElectricCar < Car; end
940
960
 
941
961
  ElectricCar.has(1, :engine)
962
+ DataMapper.finalize
942
963
  end
943
964
 
944
965
  supported_by :all do
@@ -978,6 +999,7 @@ describe DataMapper::Associations do
978
999
  belongs_to :owner, Employee, :required => false
979
1000
  has n, :employees
980
1001
  end
1002
+ DataMapper.finalize
981
1003
  end
982
1004
 
983
1005
  supported_by :all do
@@ -18,6 +18,7 @@ describe DataMapper::Model do
18
18
  has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
19
19
  end
20
20
  end
21
+ DataMapper.finalize
21
22
 
22
23
  @article_model = Blog::Article
23
24
  end
@@ -121,9 +122,9 @@ describe DataMapper::Model do
121
122
  class Article
122
123
  include DataMapper::Resource
123
124
 
124
- property :id, Serial
125
- property :title, String
126
- property :content, Text
125
+ property :id, Serial
126
+ property :title, String, :required => true, :default => 'Default Title'
127
+ property :content, Text
127
128
  property :subtitle, String
128
129
 
129
130
  belongs_to :original, self, :required => false
@@ -141,6 +142,7 @@ describe DataMapper::Model do
141
142
  has n, :articles, :through => Resource
142
143
  end
143
144
  end
145
+ DataMapper.finalize
144
146
 
145
147
  @article_model = Blog::Article
146
148
  @publication_model = Blog::Publication
@@ -160,6 +162,139 @@ describe DataMapper::Model do
160
162
  @other = @articles.create(:title => 'Other Article', :content => 'Other')
161
163
  end
162
164
 
165
+ describe '#new' do
166
+ subject { model.new(*args) }
167
+
168
+ let(:model) { @article_model }
169
+
170
+ context 'with no arguments' do
171
+ let(:args) { [] }
172
+
173
+ it { should be_instance_of(model) }
174
+
175
+ its(:attributes) { should == { :title => 'Default Title' } }
176
+ end
177
+
178
+ context 'with an empty Hash' do
179
+ let(:args) { [ {} ] }
180
+
181
+ it { should be_instance_of(model) }
182
+
183
+ its(:attributes) { should == { :title => 'Default Title' } }
184
+ end
185
+
186
+ context 'with a non-empty Hash' do
187
+ let(:attributes) { { :title => 'A Title' } }
188
+ let(:args) { [ attributes ] }
189
+
190
+ it { should be_instance_of(model) }
191
+
192
+ its(:attributes) { should == attributes }
193
+ end
194
+
195
+ context 'with nil' do
196
+ let(:args) { [ nil ] }
197
+
198
+ it { should be_instance_of(model) }
199
+
200
+ its(:attributes) { should == { :title => 'Default Title' } }
201
+ end
202
+ end
203
+
204
+ [ :create, :create! ].each do |method|
205
+ describe "##{method}" do
206
+ subject { model.send(method, *args) }
207
+
208
+ let(:model) { @article_model }
209
+
210
+ context 'with no arguments' do
211
+ let(:args) { [] }
212
+
213
+ it { should be_instance_of(model) }
214
+
215
+ it { should be_saved }
216
+ end
217
+
218
+ context 'with an empty Hash' do
219
+ let(:args) { [ {} ] }
220
+
221
+ it { should be_instance_of(model) }
222
+
223
+ it { should be_saved }
224
+ end
225
+
226
+ context 'with a non-empty Hash' do
227
+ let(:attributes) { { :title => 'A Title' } }
228
+ let(:args) { [ attributes ] }
229
+
230
+ it { should be_instance_of(model) }
231
+
232
+ it { should be_saved }
233
+
234
+ its(:title) { should == attributes[:title] }
235
+ end
236
+
237
+ context 'with nil' do
238
+ let(:args) { [ nil ] }
239
+
240
+ it { should be_instance_of(model) }
241
+
242
+ it { should be_saved }
243
+ end
244
+ end
245
+ end
246
+
247
+ [ :destroy, :destroy! ].each do |method|
248
+ describe "##{method}" do
249
+ subject { model.send(method) }
250
+
251
+ let(:model) { @article_model }
252
+
253
+ it 'should remove all resources' do
254
+ method(:subject).should change { model.any? }.from(true).to(false)
255
+ end
256
+ end
257
+ end
258
+
259
+ [ :update, :update! ].each do |method|
260
+ describe "##{method}" do
261
+ subject { model.send(method, *args) }
262
+
263
+ let(:model) { @article_model }
264
+
265
+ context 'with attributes' do
266
+ let(:attributes) { { :title => 'Updated Title' } }
267
+ let(:args) { [ attributes ] }
268
+
269
+ it { should be(true) }
270
+
271
+ it 'should persist the changes' do
272
+ subject
273
+ model.all(:fields => [ :title ]).map { |resource| resource.title }.uniq.should == [ attributes[:title] ]
274
+ end
275
+ end
276
+
277
+ context 'with attributes where one is a parent association' do
278
+ let(:attributes) { { :original => @other } }
279
+ let(:args) { [ attributes ] }
280
+
281
+ it { should be(true) }
282
+
283
+ it 'should persist the changes' do
284
+ subject
285
+ model.all(:fields => [ :original_id ]).map { |resource| resource.original }.uniq.should == [ attributes[:original] ]
286
+ end
287
+ end
288
+
289
+ context 'with attributes where a required property is nil' do
290
+ let(:attributes) { { :title => nil } }
291
+ let(:args) { [ attributes ] }
292
+
293
+ it { should be(false) }
294
+ end
295
+ end
296
+ end
297
+
163
298
  it_should_behave_like 'Finder Interface'
164
299
 
165
300
  it 'DataMapper::Model should respond to raise_on_save_failure' do
@@ -14,6 +14,7 @@ describe DataMapper::Property::Discriminator do
14
14
  class Announcement < Article; end
15
15
  class Release < Announcement; end
16
16
  end
17
+ DataMapper.finalize
17
18
 
18
19
  @article_model = Blog::Article
19
20
  @announcement_model = Blog::Announcement
@@ -12,6 +12,7 @@ describe DataMapper::Property, 'Object type' do
12
12
  end
13
13
  end
14
14
 
15
+ DataMapper.finalize
15
16
  @model = Blog::Article
16
17
  @property = @model.properties[:meta]
17
18
  end
@@ -25,6 +25,7 @@ describe DataMapper::Property do
25
25
  property :format, String, :default => 'jpeg'
26
26
  property :taken_at, Time, :default => proc { Time.now }
27
27
  end
28
+ DataMapper.finalize
28
29
  end
29
30
 
30
31
  supported_by :all do
@@ -93,8 +94,8 @@ describe DataMapper::Property do
93
94
  Track.properties[:album].index.should eql(:artist_album)
94
95
  end
95
96
 
96
- it 'returns nil when property has no index' do
97
- Track.properties[:musicbrainz_hash].index.should be_nil
97
+ it 'returns false when property has no index' do
98
+ Track.properties[:musicbrainz_hash].index.should be(false)
98
99
  end
99
100
  end
100
101
 
@@ -308,8 +309,16 @@ describe DataMapper::Property do
308
309
  Track.properties[:musicbrainz_hash].unique_index.should be(true)
309
310
  end
310
311
 
311
- it 'returns nil when property has no unique index' do
312
- Image.properties[:title].unique_index.should be_nil
312
+ it 'returns false when property has no unique index' do
313
+ Track.properties[:title].unique_index.should be(false)
314
+ end
315
+
316
+ it 'returns true when property is unique' do
317
+ Image.properties[:title].unique_index.should be(true)
318
+ end
319
+
320
+ it 'returns :key when property is a key' do
321
+ Track.properties[:id].unique_index.should == :key
313
322
  end
314
323
  end
315
324
 
@@ -59,6 +59,7 @@ describe DataMapper::Resource do
59
59
 
60
60
  property :name, String, :key => true, :default => 'a default value'
61
61
  end
62
+ DataMapper.finalize
62
63
 
63
64
  @user_model = Blog::User
64
65
  @author_model = Blog::Author
@@ -26,6 +26,8 @@ describe 'SEL', 'with STI subclasses' do
26
26
  class Comment < Message; end
27
27
  end
28
28
 
29
+ DataMapper.finalize
30
+
29
31
  @author_model = Blog::Author
30
32
  @message_model = Blog::Message
31
33
  @article_model = Blog::Article
@@ -481,51 +481,6 @@ share_examples_for 'A public Collection' do
481
481
  end
482
482
  end
483
483
 
484
- # TODO: move this to enumerable_shared_spec.rb
485
- it { should respond_to(:each) }
486
-
487
- describe '#each' do
488
- before :all do
489
- rescue_if @skip do
490
- @resources = @articles.dup.entries
491
- @resources.should_not be_empty
492
-
493
- @yield = []
494
- @collections = []
495
-
496
- @return = @articles.each do |resource|
497
- @yield << resource
498
- @collections << [ resource, resource.collection.object_id ]
499
- end
500
- end
501
- end
502
-
503
- it 'should return a Collection' do
504
- @return.should be_kind_of(DataMapper::Collection)
505
- end
506
-
507
- it 'should return self' do
508
- @return.should equal(@articles)
509
- end
510
-
511
- it 'should yield to each entry' do
512
- @yield.should == @articles
513
- end
514
-
515
- it 'should yield Resources' do
516
- @yield.each { |resource| resource.should be_kind_of(DataMapper::Resource) }
517
- end
518
-
519
- it 'should relate the Resource collection to the Collection within the block only' do
520
- pending_if 'Fix SEL for m:m', @many_to_many do
521
- @collections.each do |resource, object_id|
522
- resource.collection.should_not equal(@articles) # collection outside block
523
- object_id.should == @articles.object_id # collection inside block
524
- end
525
- end
526
- end
527
- end
528
-
529
484
  it { should respond_to(:insert) }
530
485
 
531
486
  describe '#insert' do