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.
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.rdoc +1 -1
- data/Rakefile +3 -4
- data/VERSION +1 -1
- data/dm-core.gemspec +7 -5
- data/lib/dm-core.rb +44 -0
- data/lib/dm-core/adapters.rb +1 -1
- data/lib/dm-core/adapters/abstract_adapter.rb +16 -0
- data/lib/dm-core/collection.rb +2 -2
- data/lib/dm-core/model.rb +64 -53
- data/lib/dm-core/model/property.rb +14 -6
- data/lib/dm-core/model/relationship.rb +10 -18
- data/lib/dm-core/property.rb +10 -10
- data/lib/dm-core/query.rb +8 -18
- data/lib/dm-core/resource.rb +3 -11
- data/lib/dm-core/resource/state.rb +13 -16
- data/lib/dm-core/resource/state/dirty.rb +11 -1
- data/lib/dm-core/resource/state/transient.rb +9 -1
- data/lib/dm-core/spec/lib/adapter_helpers.rb +5 -0
- data/lib/dm-core/spec/shared/adapter_spec.rb +2 -0
- data/lib/dm-core/spec/shared/resource_spec.rb +0 -31
- data/lib/dm-core/version.rb +1 -1
- data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +2 -0
- data/spec/public/associations/many_to_many_spec.rb +2 -1
- data/spec/public/associations/many_to_one_spec.rb +1 -0
- data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +1 -0
- data/spec/public/associations/one_to_many_spec.rb +2 -0
- data/spec/public/associations/one_to_one_spec.rb +2 -0
- data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +1 -0
- data/spec/public/collection_spec.rb +2 -0
- data/spec/public/finalize_spec.rb +34 -0
- data/spec/public/model/hook_spec.rb +1 -0
- data/spec/public/model/property_spec.rb +1 -0
- data/spec/public/model/relationship_spec.rb +22 -0
- data/spec/public/model_spec.rb +138 -3
- data/spec/public/property/discriminator_spec.rb +1 -0
- data/spec/public/property/object_spec.rb +1 -0
- data/spec/public/property_spec.rb +13 -4
- data/spec/public/resource_spec.rb +1 -0
- data/spec/public/sel_spec.rb +2 -0
- data/spec/public/shared/collection_shared_spec.rb +0 -45
- data/spec/public/shared/finder_shared_spec.rb +110 -0
- data/spec/public/shared/property_shared_spec.rb +1 -1
- data/spec/rcov.opts +1 -1
- data/spec/semipublic/associations/many_to_many_spec.rb +3 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +2 -0
- data/spec/semipublic/associations/one_to_many_spec.rb +2 -0
- data/spec/semipublic/associations/one_to_one_spec.rb +2 -0
- data/spec/semipublic/associations/relationship_spec.rb +6 -0
- data/spec/semipublic/query/conditions/comparison_spec.rb +3 -0
- data/spec/semipublic/query/conditions/operation_spec.rb +1 -0
- data/spec/semipublic/query/path_spec.rb +2 -0
- data/spec/semipublic/query_spec.rb +2 -3
- data/spec/semipublic/resource/state/clean_spec.rb +2 -1
- data/spec/semipublic/resource/state/deleted_spec.rb +2 -1
- data/spec/semipublic/resource/state/dirty_spec.rb +42 -20
- data/spec/semipublic/resource/state/immutable_spec.rb +7 -1
- data/spec/semipublic/resource/state/transient_spec.rb +69 -40
- data/spec/semipublic/resource/state_spec.rb +72 -66
- data/spec/semipublic/shared/property_shared_spec.rb +1 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +1 -0
- data/spec/spec_helper.rb +0 -10
- data/tasks/spec.rake +3 -0
- metadata +9 -7
@@ -21,6 +21,10 @@ share_examples_for 'Finder Interface' do
|
|
21
21
|
pending if @skip
|
22
22
|
end
|
23
23
|
|
24
|
+
it 'should be Enumerable' do
|
25
|
+
@articles.should be_kind_of(Enumerable)
|
26
|
+
end
|
27
|
+
|
24
28
|
[ :[], :slice ].each do |method|
|
25
29
|
it { @articles.should respond_to(method) }
|
26
30
|
|
@@ -880,6 +884,71 @@ share_examples_for 'Finder Interface' do
|
|
880
884
|
end
|
881
885
|
end
|
882
886
|
|
887
|
+
it { @articles.should respond_to(:each) }
|
888
|
+
|
889
|
+
describe '#each' do
|
890
|
+
subject { @articles.each(&block) }
|
891
|
+
|
892
|
+
let(:yields) { [] }
|
893
|
+
let(:block) { lambda { |resource| yields << resource } }
|
894
|
+
|
895
|
+
before do
|
896
|
+
@copy = @articles.kind_of?(Class) ? @articles : @articles.dup
|
897
|
+
@copy.to_a
|
898
|
+
end
|
899
|
+
|
900
|
+
it { should equal(@articles) }
|
901
|
+
|
902
|
+
it { method(:subject).should change { yields.dup }.from([]).to(@copy.to_a) }
|
903
|
+
end
|
904
|
+
|
905
|
+
it { @articles.should respond_to(:fetch) }
|
906
|
+
|
907
|
+
describe '#fetch' do
|
908
|
+
subject { @articles.fetch(*args, &block) }
|
909
|
+
|
910
|
+
let(:block) { nil }
|
911
|
+
|
912
|
+
context 'with a valid index and no default' do
|
913
|
+
let(:args) { [ 0 ] }
|
914
|
+
|
915
|
+
before do
|
916
|
+
@copy = @articles.kind_of?(Class) ? @articles : @articles.dup
|
917
|
+
@copy.to_a
|
918
|
+
end
|
919
|
+
|
920
|
+
should_not_be_a_kicker
|
921
|
+
|
922
|
+
it { should be_kind_of(DataMapper::Resource) }
|
923
|
+
|
924
|
+
it { should == @copy.entries.fetch(*args) }
|
925
|
+
end
|
926
|
+
|
927
|
+
context 'with an invalid index and no default' do
|
928
|
+
let(:args) { [ 42 ] }
|
929
|
+
|
930
|
+
it { method(:subject).should raise_error(IndexError) }
|
931
|
+
end
|
932
|
+
|
933
|
+
context 'with an invalid index and a default' do
|
934
|
+
let(:default) { mock('Default') }
|
935
|
+
let(:args) { [ 42, default ] }
|
936
|
+
|
937
|
+
it { should equal(default) }
|
938
|
+
end
|
939
|
+
|
940
|
+
context 'with an invalid index and a block default' do
|
941
|
+
let(:yields) { [] }
|
942
|
+
let(:default) { mock('Default') }
|
943
|
+
let(:block) { lambda { |index| yields << index; default } }
|
944
|
+
let(:args) { [ 42 ] }
|
945
|
+
|
946
|
+
it { should equal(default) }
|
947
|
+
|
948
|
+
it { method(:subject).should change { yields.dup }.from([]).to([ 42 ]) }
|
949
|
+
end
|
950
|
+
end
|
951
|
+
|
883
952
|
it { @articles.should respond_to(:first) }
|
884
953
|
|
885
954
|
describe '#first' do
|
@@ -1200,6 +1269,16 @@ share_examples_for 'Finder Interface' do
|
|
1200
1269
|
it 'should should be the last Resource in the Collection matching the query' do
|
1201
1270
|
@resource.should == @article
|
1202
1271
|
end
|
1272
|
+
|
1273
|
+
it 'should not update the original query order' do
|
1274
|
+
collection = @articles.all(:order => [ :title ])
|
1275
|
+
original_order = collection.query.order[0].dup
|
1276
|
+
last = collection.last(:content => 'Sample')
|
1277
|
+
|
1278
|
+
last.should == @resource
|
1279
|
+
|
1280
|
+
collection.query.order[0].should == original_order
|
1281
|
+
end
|
1203
1282
|
end
|
1204
1283
|
|
1205
1284
|
describe 'with a limit specified' do
|
@@ -1269,6 +1348,37 @@ share_examples_for 'Finder Interface' do
|
|
1269
1348
|
end
|
1270
1349
|
end
|
1271
1350
|
|
1351
|
+
it { @articles.should respond_to(:values_at) }
|
1352
|
+
|
1353
|
+
describe '#values_at' do
|
1354
|
+
subject { @articles.values_at(*args) }
|
1355
|
+
|
1356
|
+
before :all do
|
1357
|
+
@copy = @articles.kind_of?(Class) ? @articles : @articles.dup
|
1358
|
+
@copy.to_a
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
context 'with positive offset' do
|
1362
|
+
let(:args) { [ 0 ] }
|
1363
|
+
|
1364
|
+
should_not_be_a_kicker
|
1365
|
+
|
1366
|
+
it { should be_kind_of(Array) }
|
1367
|
+
|
1368
|
+
it { should == @copy.entries.values_at(*args) }
|
1369
|
+
end
|
1370
|
+
|
1371
|
+
describe 'with negative offset' do
|
1372
|
+
let(:args) { [ -1 ] }
|
1373
|
+
|
1374
|
+
should_not_be_a_kicker
|
1375
|
+
|
1376
|
+
it { should be_kind_of(Array) }
|
1377
|
+
|
1378
|
+
it { should == @copy.entries.values_at(*args) }
|
1379
|
+
end
|
1380
|
+
end
|
1381
|
+
|
1272
1382
|
it 'should respond to a belongs_to relationship method with #method_missing' do
|
1273
1383
|
pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
|
1274
1384
|
@articles.should respond_to(:original)
|
@@ -108,7 +108,7 @@ share_examples_for 'A public Property' do
|
|
108
108
|
[true, false].each do |value|
|
109
109
|
describe "when created with :#{method} => #{value}" do
|
110
110
|
before :all do
|
111
|
-
opt = method.to_s.
|
111
|
+
opt = method.to_s.chomp('?').to_sym
|
112
112
|
@property = @type.new(@model, @name, opt => value)
|
113
113
|
end
|
114
114
|
|
data/spec/rcov.opts
CHANGED
@@ -50,6 +50,7 @@ describe 'Many to Many Associations' do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
|
53
54
|
@article_model = Blog::Article
|
54
55
|
@author_model = Blog::Author
|
55
56
|
|
@@ -61,6 +62,8 @@ describe 'Many to Many Associations' do
|
|
61
62
|
@subject_without_default = @article_model.has(n, :without_default, 'Author', :through => :without_default_join, :via => :author)
|
62
63
|
@subject_with_default = @article_model.has(n, :with_default, 'Author', :through => :with_default_join, :via => :author, :default => @default_value)
|
63
64
|
@subject_with_default_callable = @article_model.has(n, :with_default_callable, 'Author', :through => :with_default_callable_join, :via => :author, :default => lambda { |resource, relationship| @default_value_callable })
|
65
|
+
|
66
|
+
DataMapper.finalize
|
64
67
|
end
|
65
68
|
|
66
69
|
supported_by :all do
|
@@ -32,6 +32,8 @@ describe 'One to Many Associations' do
|
|
32
32
|
@subject_without_default = @article_model.has(n, :without_default, @author_model, :child_key => [ :without_default_id ])
|
33
33
|
@subject_with_default = @article_model.has(n, :with_default, @author_model, :child_key => [ :with_default_id ], :default => @default_value)
|
34
34
|
@subject_with_default_callable = @article_model.has(n, :with_default_callable, @author_model, :child_key => [ :with_default_callable_id ], :default => lambda { |resource, relationship| @default_value_callable })
|
35
|
+
|
36
|
+
DataMapper.finalize
|
35
37
|
end
|
36
38
|
|
37
39
|
supported_by :all do
|
@@ -30,6 +30,8 @@ describe 'One to One Associations' do
|
|
30
30
|
@subject_without_default = @article_model.has(1, :without_default, @author_model, :child_key => [ :without_default_id ])
|
31
31
|
@subject_with_default = @article_model.has(1, :with_default, @author_model, :child_key => [ :with_default_id ], :default => @default_value)
|
32
32
|
@subject_with_default_callable = @article_model.has(1, :with_default_callable, @author_model, :child_key => [ :with_default_callable_id ], :default => lambda { |resource, relationship| @default_value_callable })
|
33
|
+
|
34
|
+
DataMapper.finalize
|
33
35
|
end
|
34
36
|
|
35
37
|
supported_by :all do
|
@@ -38,6 +38,7 @@ describe DataMapper::Associations::Relationship do
|
|
38
38
|
# TODO: move this to spec/public/model/relationship_spec.rb
|
39
39
|
@article_relationship.child_repository_name.should == :default
|
40
40
|
@article_relationship.parent_repository_name.should be_nil
|
41
|
+
DataMapper.finalize
|
41
42
|
end
|
42
43
|
|
43
44
|
it 'should return the inverted relationships' do
|
@@ -58,6 +59,7 @@ describe DataMapper::Associations::Relationship do
|
|
58
59
|
# TODO: move this to spec/public/model/relationship_spec.rb
|
59
60
|
@article_relationship.child_repository_name.should == :default
|
60
61
|
@article_relationship.parent_repository_name.should be_nil
|
62
|
+
DataMapper.finalize
|
61
63
|
end
|
62
64
|
|
63
65
|
it 'should return the inverted relationships' do
|
@@ -78,6 +80,7 @@ describe DataMapper::Associations::Relationship do
|
|
78
80
|
# TODO: move this to spec/public/model/relationship_spec.rb
|
79
81
|
@article_relationship.child_repository_name.should == :default
|
80
82
|
@article_relationship.parent_repository_name.should == :default
|
83
|
+
DataMapper.finalize
|
81
84
|
end
|
82
85
|
|
83
86
|
it 'should return the inverted relationships' do
|
@@ -98,6 +101,7 @@ describe DataMapper::Associations::Relationship do
|
|
98
101
|
|
99
102
|
# after Relationship#inverse to ensure no match
|
100
103
|
@expected = @comment_model.belongs_to(:article)
|
104
|
+
DataMapper.finalize
|
101
105
|
end
|
102
106
|
|
103
107
|
it 'should return a Relationship' do
|
@@ -129,6 +133,7 @@ describe DataMapper::Associations::Relationship do
|
|
129
133
|
|
130
134
|
# after Relationship#inverse to ensure no match
|
131
135
|
@expected = @article_model.has(n, :comments)
|
136
|
+
DataMapper.finalize
|
132
137
|
end
|
133
138
|
|
134
139
|
it 'should return a Relationship' do
|
@@ -156,6 +161,7 @@ describe DataMapper::Associations::Relationship do
|
|
156
161
|
describe '#valid?' do
|
157
162
|
before :all do
|
158
163
|
@relationship = @article_model.has(n, :comments)
|
164
|
+
DataMapper.finalize
|
159
165
|
end
|
160
166
|
|
161
167
|
supported_by :all do
|
@@ -14,6 +14,8 @@ shared_examples_for 'DataMapper::Query::Conditions::AbstractComparison' do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
DataMapper.finalize
|
18
|
+
|
17
19
|
@model = Blog::Article
|
18
20
|
end
|
19
21
|
|
@@ -270,6 +272,7 @@ describe DataMapper::Query::Conditions::Comparison do
|
|
270
272
|
property :title, String, :required => true
|
271
273
|
end
|
272
274
|
end
|
275
|
+
DataMapper.finalize
|
273
276
|
|
274
277
|
@model = Blog::Article
|
275
278
|
end
|
@@ -24,6 +24,7 @@ describe DataMapper::Query::Path do
|
|
24
24
|
@relationship = Author.relationships[:articles]
|
25
25
|
@relationships = [ @relationship ]
|
26
26
|
@property = Article.properties[:title]
|
27
|
+
DataMapper.finalize
|
27
28
|
end
|
28
29
|
|
29
30
|
it { DataMapper::Query::Path.should respond_to(:new) }
|
@@ -103,6 +104,7 @@ describe DataMapper::Query::Path do
|
|
103
104
|
@property = Article.properties[:title]
|
104
105
|
|
105
106
|
@path = DataMapper::Query::Path.new(@relationships)
|
107
|
+
DataMapper.finalize
|
106
108
|
end
|
107
109
|
|
108
110
|
it { @path.should respond_to(:==) }
|
@@ -1306,9 +1306,8 @@ describe DataMapper::Query do
|
|
1306
1306
|
property :id, Serial
|
1307
1307
|
end
|
1308
1308
|
|
1309
|
-
#
|
1310
|
-
|
1311
|
-
Other.send(:assert_valid)
|
1309
|
+
# finalize the models
|
1310
|
+
DataMapper.finalize
|
1312
1311
|
|
1313
1312
|
@repository = DataMapper::Repository.new(:default)
|
1314
1313
|
@model = User
|
@@ -13,6 +13,7 @@ describe DataMapper::Resource::State::Clean do
|
|
13
13
|
belongs_to :parent, self, :required => false
|
14
14
|
has n, :children, self, :inverse => :parent
|
15
15
|
end
|
16
|
+
DataMapper.finalize
|
16
17
|
|
17
18
|
@model = Author
|
18
19
|
end
|
@@ -25,7 +26,7 @@ describe DataMapper::Resource::State::Clean do
|
|
25
26
|
end
|
26
27
|
|
27
28
|
after do
|
28
|
-
@
|
29
|
+
@model.destroy!
|
29
30
|
end
|
30
31
|
|
31
32
|
[ :commit, :rollback ].each do |method|
|
@@ -14,6 +14,7 @@ describe DataMapper::Resource::State::Deleted do
|
|
14
14
|
has n, :children, self, :inverse => :parent
|
15
15
|
end
|
16
16
|
|
17
|
+
DataMapper.finalize
|
17
18
|
@model = Author
|
18
19
|
end
|
19
20
|
|
@@ -24,7 +25,7 @@ describe DataMapper::Resource::State::Deleted do
|
|
24
25
|
end
|
25
26
|
|
26
27
|
after do
|
27
|
-
@
|
28
|
+
@model.destroy!
|
28
29
|
end
|
29
30
|
|
30
31
|
describe '#commit' do
|
@@ -14,11 +14,15 @@ describe DataMapper::Resource::State::Dirty do
|
|
14
14
|
has n, :children, self, :inverse => :parent
|
15
15
|
end
|
16
16
|
|
17
|
+
DataMapper.finalize
|
18
|
+
|
17
19
|
@model = Author
|
18
20
|
end
|
19
21
|
|
20
22
|
before do
|
21
|
-
@
|
23
|
+
@parent = @model.create(:name => 'Jane Doe')
|
24
|
+
|
25
|
+
@resource = @model.create(:id => 2, :name => 'Dan Kubb', :parent => @parent)
|
22
26
|
@resource.attributes = { :name => 'John Doe' }
|
23
27
|
|
24
28
|
@state = @resource.persisted_state
|
@@ -26,35 +30,53 @@ describe DataMapper::Resource::State::Dirty do
|
|
26
30
|
end
|
27
31
|
|
28
32
|
after do
|
29
|
-
@
|
30
|
-
end
|
31
|
-
|
32
|
-
after do
|
33
|
-
@model.all.destroy!
|
33
|
+
@model.destroy!
|
34
34
|
end
|
35
35
|
|
36
36
|
describe '#commit' do
|
37
37
|
subject { @state.commit }
|
38
38
|
|
39
39
|
supported_by :all do
|
40
|
-
|
41
|
-
|
42
|
-
end
|
40
|
+
context 'with valid attributes' do
|
41
|
+
let(:state) { @state }
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
before do
|
44
|
+
@new_id = @resource.id = @resource.id.succ
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should return a Clean state' do
|
48
|
+
should eql(DataMapper::Resource::State::Clean.new(@resource))
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should set the child key if the parent key changes' do
|
52
|
+
original_id = @parent.id
|
53
|
+
@parent.update(:id => 42).should be(true)
|
54
|
+
method(:subject).should change(@resource, :parent_id).from(original_id.to_s).to('42')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should update the resource' do
|
58
|
+
subject
|
59
|
+
@model.get!(*@resource.key).should == @resource
|
60
|
+
end
|
47
61
|
|
48
|
-
|
49
|
-
|
50
|
-
|
62
|
+
it 'should update the resource to the identity map if the key changed' do
|
63
|
+
identity_map = @resource.repository.identity_map(@model)
|
64
|
+
identity_map.should == { @resource.key => @resource }
|
65
|
+
subject
|
66
|
+
identity_map.should == { [ @new_id ] => @resource }
|
67
|
+
end
|
51
68
|
end
|
52
69
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
70
|
+
context 'with invalid attributes' do
|
71
|
+
before do
|
72
|
+
@resource.coding = 'yes'
|
73
|
+
end
|
74
|
+
|
75
|
+
it { should equal(@state) }
|
76
|
+
|
77
|
+
it 'should update the resource to the identity map if the key changed' do
|
78
|
+
method(:subject).should_not change { @resource.repository.identity_map(@model).dup }
|
79
|
+
end
|
58
80
|
end
|
59
81
|
end
|
60
82
|
end
|
@@ -13,11 +13,13 @@ describe DataMapper::Resource::State::Immutable do
|
|
13
13
|
belongs_to :parent, self, :required => false
|
14
14
|
end
|
15
15
|
|
16
|
+
DataMapper.finalize
|
17
|
+
|
16
18
|
@model = Author
|
17
19
|
end
|
18
20
|
|
19
21
|
before do
|
20
|
-
@parent
|
22
|
+
@parent = @model.create(:name => 'John Doe')
|
21
23
|
|
22
24
|
@resource = @model.create(:name => 'Dan Kubb', :parent => @parent)
|
23
25
|
@resource = @model.first(@model.key.zip(@resource.key).to_hash.merge(:fields => [ :name, :parent_id ]))
|
@@ -26,6 +28,10 @@ describe DataMapper::Resource::State::Immutable do
|
|
26
28
|
@state.should be_kind_of(DataMapper::Resource::State::Immutable)
|
27
29
|
end
|
28
30
|
|
31
|
+
after do
|
32
|
+
@model.destroy!
|
33
|
+
end
|
34
|
+
|
29
35
|
describe '#commit' do
|
30
36
|
subject { @state.commit }
|
31
37
|
|