dm-core 0.9.2
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/CHANGELOG +144 -0
- data/FAQ +74 -0
- data/MIT-LICENSE +22 -0
- data/QUICKLINKS +12 -0
- data/README +143 -0
- data/lib/dm-core.rb +213 -0
- data/lib/dm-core/adapters.rb +4 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +202 -0
- data/lib/dm-core/adapters/data_objects_adapter.rb +701 -0
- data/lib/dm-core/adapters/mysql_adapter.rb +132 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +179 -0
- data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
- data/lib/dm-core/associations.rb +172 -0
- data/lib/dm-core/associations/many_to_many.rb +138 -0
- data/lib/dm-core/associations/many_to_one.rb +101 -0
- data/lib/dm-core/associations/one_to_many.rb +275 -0
- data/lib/dm-core/associations/one_to_one.rb +61 -0
- data/lib/dm-core/associations/relationship.rb +116 -0
- data/lib/dm-core/associations/relationship_chain.rb +74 -0
- data/lib/dm-core/auto_migrations.rb +64 -0
- data/lib/dm-core/collection.rb +604 -0
- data/lib/dm-core/hook.rb +11 -0
- data/lib/dm-core/identity_map.rb +45 -0
- data/lib/dm-core/is.rb +16 -0
- data/lib/dm-core/logger.rb +233 -0
- data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
- data/lib/dm-core/migrator.rb +29 -0
- data/lib/dm-core/model.rb +399 -0
- data/lib/dm-core/naming_conventions.rb +52 -0
- data/lib/dm-core/property.rb +611 -0
- data/lib/dm-core/property_set.rb +158 -0
- data/lib/dm-core/query.rb +590 -0
- data/lib/dm-core/repository.rb +159 -0
- data/lib/dm-core/resource.rb +618 -0
- data/lib/dm-core/scope.rb +35 -0
- data/lib/dm-core/support.rb +7 -0
- data/lib/dm-core/support/array.rb +13 -0
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/errors.rb +23 -0
- data/lib/dm-core/support/kernel.rb +7 -0
- data/lib/dm-core/support/symbol.rb +41 -0
- data/lib/dm-core/transaction.rb +267 -0
- data/lib/dm-core/type.rb +160 -0
- data/lib/dm-core/type_map.rb +80 -0
- data/lib/dm-core/types.rb +19 -0
- data/lib/dm-core/types/boolean.rb +7 -0
- data/lib/dm-core/types/discriminator.rb +32 -0
- data/lib/dm-core/types/object.rb +20 -0
- data/lib/dm-core/types/paranoid_boolean.rb +23 -0
- data/lib/dm-core/types/paranoid_datetime.rb +22 -0
- data/lib/dm-core/types/serial.rb +9 -0
- data/lib/dm-core/types/text.rb +10 -0
- data/spec/integration/association_spec.rb +1215 -0
- data/spec/integration/association_through_spec.rb +150 -0
- data/spec/integration/associations/many_to_many_spec.rb +171 -0
- data/spec/integration/associations/many_to_one_spec.rb +123 -0
- data/spec/integration/associations/one_to_many_spec.rb +66 -0
- data/spec/integration/auto_migrations_spec.rb +398 -0
- data/spec/integration/collection_spec.rb +1015 -0
- data/spec/integration/data_objects_adapter_spec.rb +32 -0
- data/spec/integration/model_spec.rb +68 -0
- data/spec/integration/mysql_adapter_spec.rb +85 -0
- data/spec/integration/postgres_adapter_spec.rb +732 -0
- data/spec/integration/property_spec.rb +224 -0
- data/spec/integration/query_spec.rb +376 -0
- data/spec/integration/repository_spec.rb +57 -0
- data/spec/integration/resource_spec.rb +324 -0
- data/spec/integration/sqlite3_adapter_spec.rb +352 -0
- data/spec/integration/sti_spec.rb +185 -0
- data/spec/integration/transaction_spec.rb +75 -0
- data/spec/integration/type_spec.rb +149 -0
- data/spec/lib/mock_adapter.rb +27 -0
- data/spec/spec_helper.rb +112 -0
- data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
- data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
- data/spec/unit/adapters/data_objects_adapter_spec.rb +627 -0
- data/spec/unit/adapters/postgres_adapter_spec.rb +125 -0
- data/spec/unit/associations/many_to_many_spec.rb +14 -0
- data/spec/unit/associations/many_to_one_spec.rb +138 -0
- data/spec/unit/associations/one_to_many_spec.rb +385 -0
- data/spec/unit/associations/one_to_one_spec.rb +7 -0
- data/spec/unit/associations/relationship_spec.rb +67 -0
- data/spec/unit/associations_spec.rb +205 -0
- data/spec/unit/auto_migrations_spec.rb +110 -0
- data/spec/unit/collection_spec.rb +174 -0
- data/spec/unit/data_mapper_spec.rb +21 -0
- data/spec/unit/identity_map_spec.rb +126 -0
- data/spec/unit/is_spec.rb +80 -0
- data/spec/unit/migrator_spec.rb +33 -0
- data/spec/unit/model_spec.rb +339 -0
- data/spec/unit/naming_conventions_spec.rb +28 -0
- data/spec/unit/property_set_spec.rb +96 -0
- data/spec/unit/property_spec.rb +447 -0
- data/spec/unit/query_spec.rb +485 -0
- data/spec/unit/repository_spec.rb +93 -0
- data/spec/unit/resource_spec.rb +557 -0
- data/spec/unit/scope_spec.rb +131 -0
- data/spec/unit/transaction_spec.rb +493 -0
- data/spec/unit/type_map_spec.rb +114 -0
- data/spec/unit/type_spec.rb +119 -0
- metadata +187 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
if ADAPTER
|
|
4
|
+
describe 'through-associations' do
|
|
5
|
+
before :all do
|
|
6
|
+
repository(ADAPTER) do
|
|
7
|
+
|
|
8
|
+
class Tag
|
|
9
|
+
include DataMapper::Resource
|
|
10
|
+
def self.default_repository_name
|
|
11
|
+
ADAPTER
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
property :id, Serial
|
|
15
|
+
property :title, String
|
|
16
|
+
property :voided, Boolean, :default => false
|
|
17
|
+
|
|
18
|
+
has n, :taggings
|
|
19
|
+
|
|
20
|
+
has n, :relationships
|
|
21
|
+
has n, :related_posts, :through => :relationships, :class_name => 'Post'
|
|
22
|
+
|
|
23
|
+
has n, :posts, :through => :taggings
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Tagging
|
|
27
|
+
include DataMapper::Resource
|
|
28
|
+
def self.default_repository_name
|
|
29
|
+
ADAPTER
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
property :id, Serial
|
|
33
|
+
property :title, String
|
|
34
|
+
|
|
35
|
+
belongs_to :post
|
|
36
|
+
belongs_to :tag
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class Post
|
|
40
|
+
include DataMapper::Resource
|
|
41
|
+
def self.default_repository_name
|
|
42
|
+
ADAPTER
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
property :id, Serial
|
|
46
|
+
property :title, String
|
|
47
|
+
|
|
48
|
+
has n, :taggings
|
|
49
|
+
has n, :tags, :through => :taggings
|
|
50
|
+
|
|
51
|
+
has n, :relationships
|
|
52
|
+
has n, :related_posts,
|
|
53
|
+
:through => :relationships,
|
|
54
|
+
:class_name => "Post"
|
|
55
|
+
|
|
56
|
+
has n, :void_tags,
|
|
57
|
+
:through => :taggings,
|
|
58
|
+
:class_name => "Tag",
|
|
59
|
+
:remote_relationship_name => :tag,
|
|
60
|
+
Post.taggings.tag.voided => true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class Relationship
|
|
64
|
+
include DataMapper::Resource
|
|
65
|
+
def self.default_repository_name
|
|
66
|
+
ADAPTER
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
property :id, Serial
|
|
70
|
+
belongs_to :post
|
|
71
|
+
belongs_to :related_post, :class_name => "Post"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
[Post, Tag, Tagging, Relationship].each do |descendant|
|
|
75
|
+
descendant.auto_migrate!(ADAPTER)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
post = Post.create(:title => "Entry")
|
|
79
|
+
another_post = Post.create(:title => "Another")
|
|
80
|
+
|
|
81
|
+
crappy = Tagging.new
|
|
82
|
+
post.taggings << crappy
|
|
83
|
+
post.save
|
|
84
|
+
|
|
85
|
+
crap = Tag.create(:title => "crap")
|
|
86
|
+
crap.taggings << crappy
|
|
87
|
+
crap.save
|
|
88
|
+
|
|
89
|
+
crappier = Tagging.new
|
|
90
|
+
post.taggings << crappier
|
|
91
|
+
post.save
|
|
92
|
+
|
|
93
|
+
crapz = Tag.create(:title => "crapz", :voided => true)
|
|
94
|
+
crapz.taggings << crappier
|
|
95
|
+
crapz.save
|
|
96
|
+
|
|
97
|
+
goody = Tagging.new
|
|
98
|
+
another_post.taggings << goody
|
|
99
|
+
another_post.save
|
|
100
|
+
|
|
101
|
+
good = Tag.create(:title => "good")
|
|
102
|
+
good.taggings << goody
|
|
103
|
+
good.save
|
|
104
|
+
|
|
105
|
+
relation = Relationship.new(:related_post => another_post)
|
|
106
|
+
post.relationships << relation
|
|
107
|
+
post.save
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'should return the right children for has n => belongs_to relationships' do
|
|
112
|
+
Post.first.tags.select do |tag|
|
|
113
|
+
tag.title == 'crap'
|
|
114
|
+
end.size.should == 1
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'should return the right children for has n => belongs_to self-referential relationships' do
|
|
118
|
+
Post.first.related_posts.select do |post|
|
|
119
|
+
post.title == 'Another'
|
|
120
|
+
end.size.should == 1
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'should handle all()' do
|
|
124
|
+
related_posts = Post.first.related_posts
|
|
125
|
+
related_posts.all.object_id.should == related_posts.object_id
|
|
126
|
+
related_posts.all(:id => 2).first.should == Post.get!(2)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'should handle first()' do
|
|
130
|
+
post = Post.get!(2)
|
|
131
|
+
related_posts = Post.first.related_posts
|
|
132
|
+
related_posts.first.should == post
|
|
133
|
+
related_posts.first(10).should == [ post ]
|
|
134
|
+
related_posts.first(:id => 2).should == post
|
|
135
|
+
related_posts.first(10, :id => 2).map { |r| r.id }.should == [ post.id ]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'should proxy object should be frozen' do
|
|
139
|
+
Post.first.related_posts.should be_frozen
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "should respect tagging with conditions" do
|
|
143
|
+
post = Post.get(1)
|
|
144
|
+
post.tags.size
|
|
145
|
+
post.tags.select{|t| t.voided == true}.size.should == 1
|
|
146
|
+
post.void_tags.size.should == 1
|
|
147
|
+
post.void_tags.all?{|t| t.voided == true}.should be_true
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe DataMapper::Associations::ManyToMany::Proxy do
|
|
4
|
+
before :all do
|
|
5
|
+
class Editor
|
|
6
|
+
include DataMapper::Resource
|
|
7
|
+
|
|
8
|
+
def self.default_repository_name; ADAPTER end
|
|
9
|
+
|
|
10
|
+
property :id, Serial
|
|
11
|
+
property :name, String
|
|
12
|
+
|
|
13
|
+
has n, :books, :through => Resource
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Book
|
|
17
|
+
include DataMapper::Resource
|
|
18
|
+
|
|
19
|
+
def self.default_repository_name; ADAPTER end
|
|
20
|
+
|
|
21
|
+
property :id, Serial
|
|
22
|
+
property :title, String
|
|
23
|
+
|
|
24
|
+
has n, :editors, :through => Resource
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
[ Book, Editor, BookEditor ].each { |k| k.auto_migrate! }
|
|
28
|
+
|
|
29
|
+
repository(ADAPTER) do
|
|
30
|
+
book_1 = Book.create(:title => "Dubliners")
|
|
31
|
+
book_2 = Book.create(:title => "Portrait of the Artist as a Young Man")
|
|
32
|
+
book_3 = Book.create(:title => "Ulysses")
|
|
33
|
+
|
|
34
|
+
editor_1 = Editor.create(:name => "Jon Doe")
|
|
35
|
+
editor_2 = Editor.create(:name => "Jane Doe")
|
|
36
|
+
|
|
37
|
+
BookEditor.create(:book => book_1, :editor => editor_1)
|
|
38
|
+
BookEditor.create(:book => book_2, :editor => editor_1)
|
|
39
|
+
BookEditor.create(:book => book_1, :editor => editor_2)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should correctly link records" do
|
|
44
|
+
Editor.get(1).books.size.should == 2
|
|
45
|
+
Editor.get(2).books.size.should == 1
|
|
46
|
+
Book.get(1).editors.size.should == 2
|
|
47
|
+
Book.get(2).editors.size.should == 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should be able to have associated objects manually added" do
|
|
51
|
+
book = Book.get(3)
|
|
52
|
+
# book.editors.size.should == 0
|
|
53
|
+
|
|
54
|
+
be = BookEditor.new(:book_id => book.id, :editor_id => 2)
|
|
55
|
+
book.book_editors << be
|
|
56
|
+
book.save
|
|
57
|
+
|
|
58
|
+
book.reload
|
|
59
|
+
book.editors.size.should == 1
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should automatically added necessary through class" do
|
|
63
|
+
book = Book.get(3)
|
|
64
|
+
book.editors << Editor.get(1)
|
|
65
|
+
book.editors << Editor.new(:name => "Jimmy John")
|
|
66
|
+
book.save
|
|
67
|
+
book.editors.size.should == 3
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should react correctly to a new record" do
|
|
71
|
+
book = Book.new(:title => "Finnegan's Wake")
|
|
72
|
+
book.editors << Editor.get(2)
|
|
73
|
+
book.save
|
|
74
|
+
book.editors.size.should == 1
|
|
75
|
+
Editor.get(2).books.size.should == 3
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should be able to delete intermediate model" do
|
|
79
|
+
book = Book.get(3)
|
|
80
|
+
be = BookEditor.get(3,1)
|
|
81
|
+
book.book_editors.delete(be)
|
|
82
|
+
book.save
|
|
83
|
+
book.reload
|
|
84
|
+
book = Book.get(3)
|
|
85
|
+
book.book_editors.size.should == 2
|
|
86
|
+
book.editors.size.should == 2
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "should be clearable" do
|
|
90
|
+
repository(ADAPTER) do
|
|
91
|
+
book = Book.get(2)
|
|
92
|
+
book.editors.size.should == 1
|
|
93
|
+
book.editors.clear
|
|
94
|
+
book.save
|
|
95
|
+
book.reload
|
|
96
|
+
book.book_editors.size.should == 0
|
|
97
|
+
book.editors.size.should == 0
|
|
98
|
+
end
|
|
99
|
+
repository(ADAPTER) do
|
|
100
|
+
Book.get(2).editors.size.should == 0
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should be able to delete one object" do
|
|
105
|
+
book = Book.get(1)
|
|
106
|
+
editor = book.editors.first
|
|
107
|
+
|
|
108
|
+
book.editors.size.should == 2
|
|
109
|
+
book.editors.delete(editor)
|
|
110
|
+
book.book_editors.size.should == 1
|
|
111
|
+
book.editors.size.should == 1
|
|
112
|
+
book.save
|
|
113
|
+
book.reload
|
|
114
|
+
Editor.get(1).books.should_not include(book)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "should be destroyable" do
|
|
118
|
+
pending 'cannot destroy a collection yet' do
|
|
119
|
+
book = Book.get(3)
|
|
120
|
+
book.editors.destroy
|
|
121
|
+
book.save
|
|
122
|
+
book.reload
|
|
123
|
+
book.editors.size.should == 0
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
describe 'with natural keys' do
|
|
128
|
+
before :all do
|
|
129
|
+
class Author
|
|
130
|
+
include DataMapper::Resource
|
|
131
|
+
|
|
132
|
+
def self.default_repository_name; ADAPTER end
|
|
133
|
+
|
|
134
|
+
property :name, String, :key => true
|
|
135
|
+
|
|
136
|
+
has n, :books, :through => Resource
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class Book
|
|
140
|
+
has n, :authors, :through => Resource
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
[ Author, AuthorBook ].each { |k| k.auto_migrate! }
|
|
144
|
+
|
|
145
|
+
@author = Author.create(:name => 'James Joyce')
|
|
146
|
+
|
|
147
|
+
@book_1 = Book.get!(1)
|
|
148
|
+
@book_2 = Book.get!(2)
|
|
149
|
+
@book_3 = Book.get!(3)
|
|
150
|
+
|
|
151
|
+
AuthorBook.create(:book => @book_1, :author => @author)
|
|
152
|
+
AuthorBook.create(:book => @book_2, :author => @author)
|
|
153
|
+
AuthorBook.create(:book => @book_3, :author => @author)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'should have a join resource where the natural key is a property' do
|
|
157
|
+
AuthorBook.properties[:author_name].primitive.should == String
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'should have a join resource where every property is part of the key' do
|
|
161
|
+
AuthorBook.key.should == AuthorBook.properties.to_a
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'should correctly link records' do
|
|
165
|
+
@author.books.should have(3).entries
|
|
166
|
+
@book_1.authors.should have(1).entries
|
|
167
|
+
@book_2.authors.should have(1).entries
|
|
168
|
+
@book_3.authors.should have(1).entries
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
if ADAPTER
|
|
4
|
+
module ManyToOneSpec
|
|
5
|
+
class Parent
|
|
6
|
+
include DataMapper::Resource
|
|
7
|
+
|
|
8
|
+
def self.default_repository_name
|
|
9
|
+
ADAPTER
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
property :id, Serial
|
|
13
|
+
property :name, String
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Child
|
|
17
|
+
include DataMapper::Resource
|
|
18
|
+
|
|
19
|
+
def self.default_repository_name
|
|
20
|
+
ADAPTER
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
property :id, Serial
|
|
24
|
+
property :name, String
|
|
25
|
+
|
|
26
|
+
belongs_to :parent, :class_name => 'ManyToOneSpec::Parent'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe DataMapper::Associations::ManyToOne::Proxy do
|
|
31
|
+
before do
|
|
32
|
+
ManyToOneSpec::Parent.auto_migrate!
|
|
33
|
+
ManyToOneSpec::Child.auto_migrate!
|
|
34
|
+
|
|
35
|
+
@parent = ManyToOneSpec::Parent.create(:name => 'parent')
|
|
36
|
+
@child = ManyToOneSpec::Child.create(:name => 'child', :parent => @parent)
|
|
37
|
+
@other = ManyToOneSpec::Parent.create(:name => 'other parent')
|
|
38
|
+
@association = @child.parent
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '#replace' do
|
|
42
|
+
it 'should remove the resource from the collection' do
|
|
43
|
+
@association.should == @parent
|
|
44
|
+
@association.replace(@other)
|
|
45
|
+
@association.should == @other
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should not automatically save that the resource was removed from the association' do
|
|
49
|
+
@association.replace(@other)
|
|
50
|
+
@child.reload.parent.should == @parent
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'should return the association' do
|
|
54
|
+
@association.replace(@other).object_id.should == @association.object_id
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe '#save' do
|
|
59
|
+
describe 'when the parent is nil' do
|
|
60
|
+
before do
|
|
61
|
+
@association.replace(nil)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should not save the parent' do
|
|
65
|
+
@association.save
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'should return false' do
|
|
69
|
+
@association.save.should == false
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe 'when the parent is not a new record' do
|
|
74
|
+
before do
|
|
75
|
+
@parent.should_not be_new_record
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should not save the parent' do
|
|
79
|
+
@parent.should_not_receive(:save)
|
|
80
|
+
@association.save
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'should return true' do
|
|
84
|
+
@association.save.should == true
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe 'when the parent is a new record' do
|
|
89
|
+
before do
|
|
90
|
+
@parent = ManyToOneSpec::Parent.new(:name => 'unsaved parent')
|
|
91
|
+
@parent.should be_new_record
|
|
92
|
+
@association.replace(@parent)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'should save the parent' do
|
|
96
|
+
@association.save
|
|
97
|
+
@parent.should_not be_new_record
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should return the result of the save' do
|
|
101
|
+
@association.save.should == true
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe '#reload' do
|
|
107
|
+
before do
|
|
108
|
+
@child.parent_id.should == @parent.id
|
|
109
|
+
@association.replace(@other)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'should not change the foreign key in the child' do
|
|
113
|
+
@child.parent_id.should == @other.id
|
|
114
|
+
@association.reload
|
|
115
|
+
@child.parent_id.should == @other.id
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'should return self' do
|
|
119
|
+
@association.reload.object_id.should == @association.object_id
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
require 'pp'
|
|
3
|
+
describe "OneToMany" do
|
|
4
|
+
before(:all) do
|
|
5
|
+
class Team
|
|
6
|
+
include DataMapper::Resource
|
|
7
|
+
|
|
8
|
+
def self.default_repository_name; ADAPTER end
|
|
9
|
+
|
|
10
|
+
property :id, Serial
|
|
11
|
+
property :name, String
|
|
12
|
+
|
|
13
|
+
has n, :players
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Player
|
|
17
|
+
include DataMapper::Resource
|
|
18
|
+
|
|
19
|
+
def self.default_repository_name; ADAPTER end
|
|
20
|
+
|
|
21
|
+
property :id, Serial
|
|
22
|
+
property :name, String
|
|
23
|
+
|
|
24
|
+
belongs_to :team
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
[Team, Player].each { |k| k.auto_migrate!(ADAPTER) }
|
|
28
|
+
|
|
29
|
+
Team.create!(:name => "Cowboys")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "unsaved parent model should accept array of hashes for association" do
|
|
33
|
+
players = [{ :name => "Brett Favre" }, { :name => "Reggie White" }]
|
|
34
|
+
|
|
35
|
+
team = Team.new(:name => "Packers", :players => players)
|
|
36
|
+
team.players.zip(players) do |player, values|
|
|
37
|
+
player.should be_an_instance_of(Player)
|
|
38
|
+
values.each { |k, v| player.send(k).should == v }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
players = team.players
|
|
42
|
+
team.save
|
|
43
|
+
|
|
44
|
+
repository(ADAPTER) do
|
|
45
|
+
Team.get(2).players.should == players
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "saved parent model should accept array of hashes for association" do
|
|
50
|
+
players = [{ :name => "Troy Aikman" }, { :name => "Chad Hennings" }]
|
|
51
|
+
|
|
52
|
+
team = Team.get(1)
|
|
53
|
+
team.players = players
|
|
54
|
+
team.players.zip(players) do |player, values|
|
|
55
|
+
player.should be_an_instance_of(Player)
|
|
56
|
+
values.each { |k, v| player.send(k).should == v }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
players = team.players
|
|
60
|
+
team.save
|
|
61
|
+
|
|
62
|
+
repository(ADAPTER) do
|
|
63
|
+
Team.get(1).players.should == players
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|