mongo_mapper-rails3 0.7.0.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.
Files changed (94) hide show
  1. data/.gitignore +10 -0
  2. data/Gemfile +15 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +60 -0
  5. data/Rakefile +58 -0
  6. data/VERSION +1 -0
  7. data/bin/mmconsole +60 -0
  8. data/lib/mongo_mapper.rb +131 -0
  9. data/lib/mongo_mapper/document.rb +439 -0
  10. data/lib/mongo_mapper/embedded_document.rb +68 -0
  11. data/lib/mongo_mapper/plugins.rb +30 -0
  12. data/lib/mongo_mapper/plugins/associations.rb +106 -0
  13. data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
  14. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  15. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  16. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  17. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
  18. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +141 -0
  19. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  20. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +120 -0
  21. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  22. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  23. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  24. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  25. data/lib/mongo_mapper/plugins/associations/proxy.rb +119 -0
  26. data/lib/mongo_mapper/plugins/callbacks.rb +87 -0
  27. data/lib/mongo_mapper/plugins/clone.rb +14 -0
  28. data/lib/mongo_mapper/plugins/descendants.rb +17 -0
  29. data/lib/mongo_mapper/plugins/dirty.rb +120 -0
  30. data/lib/mongo_mapper/plugins/equality.rb +24 -0
  31. data/lib/mongo_mapper/plugins/identity_map.rb +124 -0
  32. data/lib/mongo_mapper/plugins/inspect.rb +15 -0
  33. data/lib/mongo_mapper/plugins/keys.rb +310 -0
  34. data/lib/mongo_mapper/plugins/logger.rb +19 -0
  35. data/lib/mongo_mapper/plugins/pagination.rb +26 -0
  36. data/lib/mongo_mapper/plugins/pagination/proxy.rb +72 -0
  37. data/lib/mongo_mapper/plugins/protected.rb +46 -0
  38. data/lib/mongo_mapper/plugins/rails.rb +46 -0
  39. data/lib/mongo_mapper/plugins/serialization.rb +50 -0
  40. data/lib/mongo_mapper/plugins/validations.rb +88 -0
  41. data/lib/mongo_mapper/query.rb +130 -0
  42. data/lib/mongo_mapper/support.rb +217 -0
  43. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  44. data/lib/mongo_mapper/support/find.rb +77 -0
  45. data/mongo_mapper-rails3.gemspec +208 -0
  46. data/performance/read_write.rb +52 -0
  47. data/specs.watchr +51 -0
  48. data/test/NOTE_ON_TESTING +1 -0
  49. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  50. data/test/functional/associations/test_belongs_to_proxy.rb +101 -0
  51. data/test/functional/associations/test_in_array_proxy.rb +321 -0
  52. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  53. data/test/functional/associations/test_many_documents_proxy.rb +453 -0
  54. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  55. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  56. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  57. data/test/functional/associations/test_one_proxy.rb +161 -0
  58. data/test/functional/test_associations.rb +44 -0
  59. data/test/functional/test_binary.rb +27 -0
  60. data/test/functional/test_callbacks.rb +81 -0
  61. data/test/functional/test_dirty.rb +163 -0
  62. data/test/functional/test_document.rb +1244 -0
  63. data/test/functional/test_embedded_document.rb +125 -0
  64. data/test/functional/test_identity_map.rb +508 -0
  65. data/test/functional/test_logger.rb +20 -0
  66. data/test/functional/test_modifiers.rb +252 -0
  67. data/test/functional/test_pagination.rb +93 -0
  68. data/test/functional/test_protected.rb +161 -0
  69. data/test/functional/test_string_id_compatibility.rb +67 -0
  70. data/test/functional/test_validations.rb +329 -0
  71. data/test/models.rb +232 -0
  72. data/test/support/custom_matchers.rb +55 -0
  73. data/test/support/timing.rb +16 -0
  74. data/test/test_helper.rb +59 -0
  75. data/test/unit/associations/test_base.rb +207 -0
  76. data/test/unit/associations/test_proxy.rb +105 -0
  77. data/test/unit/serializers/test_json_serializer.rb +189 -0
  78. data/test/unit/test_descendant_appends.rb +71 -0
  79. data/test/unit/test_document.rb +231 -0
  80. data/test/unit/test_dynamic_finder.rb +123 -0
  81. data/test/unit/test_embedded_document.rb +663 -0
  82. data/test/unit/test_keys.rb +169 -0
  83. data/test/unit/test_lint.rb +8 -0
  84. data/test/unit/test_mongo_mapper.rb +125 -0
  85. data/test/unit/test_pagination.rb +160 -0
  86. data/test/unit/test_plugins.rb +51 -0
  87. data/test/unit/test_query.rb +334 -0
  88. data/test/unit/test_rails.rb +123 -0
  89. data/test/unit/test_rails_compatibility.rb +57 -0
  90. data/test/unit/test_serialization.rb +51 -0
  91. data/test/unit/test_support.rb +362 -0
  92. data/test/unit/test_time_zones.rb +39 -0
  93. data/test/unit/test_validations.rb +557 -0
  94. metadata +344 -0
@@ -0,0 +1,229 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ Post.collection.remove
7
+ PostComment.collection.remove
8
+ end
9
+
10
+ should "default reader to empty array" do
11
+ Post.new.comments.should == []
12
+ end
13
+
14
+ should "add type and id key to polymorphic class base" do
15
+ PostComment.keys.keys.should include('commentable_type')
16
+ PostComment.keys.keys.should include('commentable_id')
17
+ end
18
+
19
+ should "allow adding to association like it was an array" do
20
+ post = Post.new
21
+ post.comments << PostComment.new(:body => 'foo bar')
22
+ post.comments << PostComment.new(:body => 'baz')
23
+ post.comments.concat PostComment.new(:body => 'baz')
24
+
25
+ post.comments.size.should == 3
26
+ end
27
+
28
+ should "be able to replace the association" do
29
+ post = Post.new
30
+
31
+ lambda {
32
+ post.comments = [
33
+ PostComment.new(:body => 'foo'),
34
+ PostComment.new(:body => 'bar'),
35
+ PostComment.new(:body => 'baz')
36
+ ]
37
+ }.should change { PostComment.count }.by(3)
38
+
39
+ post = post.reload
40
+ post.comments.size.should == 3
41
+ bodies = post.comments.collect(&:body)
42
+ bodies.should include('foo')
43
+ bodies.should include('bar')
44
+ bodies.should include('baz')
45
+ end
46
+
47
+ context "build" do
48
+ should "assign foreign key" do
49
+ post = Post.new
50
+ comment = post.comments.build
51
+ comment.commentable_id.should == post._id
52
+ end
53
+
54
+ should "assign _type" do
55
+ post = Post.new
56
+ comment = post.comments.build
57
+ comment.commentable_type.should == "Post"
58
+ end
59
+
60
+ should "allow assigning attributes" do
61
+ post = Post.new
62
+ comment = post.comments.build(:body => 'foo bar')
63
+ comment.body.should == 'foo bar'
64
+ end
65
+ end
66
+
67
+ context "create" do
68
+ should "assign foreign key" do
69
+ post = Post.new
70
+ comment = post.comments.create
71
+ comment.commentable_id.should == post._id
72
+ end
73
+
74
+ should "assign _type" do
75
+ post = Post.new
76
+ comment = post.comments.create
77
+ comment.commentable_type.should == "Post"
78
+ end
79
+
80
+ should "save record" do
81
+ post = Post.new
82
+ lambda {
83
+ post.comments.create(:body => 'baz')
84
+ }.should change { PostComment.count }
85
+ end
86
+
87
+ should "allow passing attributes" do
88
+ post = Post.create
89
+ comment = post.comments.create(:body => 'foo bar')
90
+ comment.body.should == 'foo bar'
91
+ end
92
+ end
93
+
94
+ context "count" do
95
+ should "work scoped to association" do
96
+ post = Post.create
97
+ 3.times { post.comments.create(:body => 'foo bar') }
98
+
99
+ other_post = Post.create
100
+ 2.times { other_post.comments.create(:body => 'baz') }
101
+
102
+ post.comments.count.should == 3
103
+ other_post.comments.count.should == 2
104
+ end
105
+
106
+ should "work with conditions" do
107
+ post = Post.create
108
+ post.comments.create(:body => 'foo bar')
109
+ post.comments.create(:body => 'baz')
110
+ post.comments.create(:body => 'foo bar')
111
+
112
+ post.comments.count(:body => 'foo bar').should == 2
113
+ end
114
+ end
115
+
116
+ context "Finding scoped to association" do
117
+ setup do
118
+ @post = Post.new
119
+
120
+ @comment1 = PostComment.create(:body => 'comment1', :name => 'John')
121
+ @comment2 = PostComment.create(:body => 'comment2', :name => 'Steve')
122
+ @comment3 = PostComment.create(:body => 'comment3', :name => 'John')
123
+ @post.comments = [@comment1, @comment2]
124
+ @post.save
125
+
126
+ @post2 = Post.create(:body => "post #2")
127
+ @comment4 = PostComment.create(:body => 'comment1', :name => 'Chas')
128
+ @comment5 = PostComment.create(:body => 'comment2', :name => 'Dan')
129
+ @comment6 = PostComment.create(:body => 'comment3', :name => 'Ed')
130
+ @post2.comments = [@comment4, @comment5, @comment6]
131
+ @post2.save
132
+ end
133
+
134
+ context "with #all" do
135
+ should "work" do
136
+ @post.comments.all.should include(@comment1)
137
+ @post.comments.all.should include(@comment2)
138
+ end
139
+
140
+ should "work with conditions" do
141
+ comments = @post.comments.all(:body => 'comment1')
142
+ comments.should == [@comment1]
143
+ end
144
+
145
+ should "work with order" do
146
+ comments = @post.comments.all(:order => 'body desc')
147
+ comments.should == [@comment2, @comment1]
148
+ end
149
+ end
150
+
151
+ context "with one id" do
152
+ should "work for id in association" do
153
+ @post.comments.find(@comment2._id).should == @comment2
154
+ end
155
+
156
+ should "not work for id not in association" do
157
+ assert_raises(MongoMapper::DocumentNotFound) do
158
+ @post.comments.find!(@comment5._id)
159
+ end
160
+ end
161
+ end
162
+
163
+ context "with multiple ids" do
164
+ should "work for ids in association" do
165
+ posts = @post.comments.find!(@comment1._id, @comment2._id)
166
+ posts.should == [@comment1, @comment2]
167
+ end
168
+
169
+ should "not work for ids not in association" do
170
+ assert_raises(MongoMapper::DocumentNotFound) do
171
+ @post.comments.find!(@comment1._id, @comment2._id, @comment4._id)
172
+ end
173
+ end
174
+ end
175
+
176
+ context "dynamic finders" do
177
+ should "work with single key" do
178
+ @post.comments.find_by_body('comment1').should == @comment1
179
+ @post2.comments.find_by_body('comment1').should == @comment4
180
+ end
181
+
182
+ should "work with multiple keys" do
183
+ @post.comments.find_by_body_and_name('comment1', 'John').should == @comment1
184
+ @post.comments.find_by_body_and_name('comment1', 'Frank').should be_nil
185
+ end
186
+
187
+ should "raise error when using !" do
188
+ lambda {
189
+ @post.comments.find_by_body!('asdf')
190
+ }.should raise_error(MongoMapper::DocumentNotFound)
191
+ end
192
+
193
+ context "find_or_create_by" do
194
+ should "not create document if found" do
195
+ lambda {
196
+ comment = @post.comments.find_or_create_by_name('Steve')
197
+ comment.commentable.should == @post
198
+ comment.should == @comment2
199
+ }.should_not change { PostComment.count }
200
+ end
201
+
202
+ should "create document if not found" do
203
+ lambda {
204
+ @post.comments.find_or_create_by_name('Chas')
205
+ }.should change { PostComment.count }.by(1)
206
+ end
207
+ end
208
+ end
209
+
210
+ context "with #paginate" do
211
+ setup do
212
+ @comments = @post2.comments.paginate(:per_page => 2, :page => 1, :order => 'name')
213
+ end
214
+
215
+ should "return total pages" do
216
+ @comments.total_pages.should == 2
217
+ end
218
+
219
+ should "return total entries" do
220
+ @comments.total_entries.should == 3
221
+ end
222
+
223
+ should "return the subject" do
224
+ @comments.should include(@comment4)
225
+ @comments.should include(@comment5)
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,453 @@
1
+ require 'test_helper'
2
+ require 'models'
3
+
4
+ class ManyDocumentsProxyTest < Test::Unit::TestCase
5
+ def setup
6
+ Project.collection.remove
7
+ Status.collection.remove
8
+ end
9
+
10
+ should "default reader to empty array" do
11
+ project = Project.new
12
+ project.statuses.should == []
13
+ end
14
+
15
+ should "allow adding to association like it was an array" do
16
+ project = Project.new
17
+ project.statuses << Status.new(:name => 'Foo1!')
18
+ project.statuses.push Status.new(:name => 'Foo2!')
19
+ project.statuses.concat Status.new(:name => 'Foo3!')
20
+ project.statuses.size.should == 3
21
+ end
22
+
23
+ should "be able to replace the association" do
24
+ project = Project.new
25
+ project.statuses = [Status.new(:name => "ready")]
26
+ project.save.should be_true
27
+
28
+ project.reload
29
+ project.statuses.size.should == 1
30
+ project.statuses[0].name.should == "ready"
31
+ end
32
+
33
+ should "correctly assign foreign key when using <<, push and concat" do
34
+ project = Project.new
35
+ project.statuses << Status.new(:name => '<<')
36
+ project.statuses.push Status.new(:name => 'push')
37
+ project.statuses.concat Status.new(:name => 'concat')
38
+
39
+ project.reload
40
+ project.statuses[0].project_id.should == project.id
41
+ project.statuses[1].project_id.should == project.id
42
+ project.statuses[2].project_id.should == project.id
43
+ end
44
+
45
+ context "build" do
46
+ should "assign foreign key" do
47
+ project = Project.create
48
+ status = project.statuses.build
49
+ status.project_id.should == project.id
50
+ end
51
+
52
+ should "allow assigning attributes" do
53
+ project = Project.create
54
+ status = project.statuses.build(:name => 'Foo')
55
+ status.name.should == 'Foo'
56
+ end
57
+
58
+ should "reset cache" do
59
+ project = Project.create
60
+ project.statuses.size.should == 0
61
+ status = project.statuses.build(:name => 'Foo')
62
+ status.save!
63
+ project.statuses.size.should == 1
64
+ end
65
+ end
66
+
67
+ context "create" do
68
+ should "assign foreign key" do
69
+ project = Project.create
70
+ status = project.statuses.create(:name => 'Foo!')
71
+ status.project_id.should == project.id
72
+ end
73
+
74
+ should "save record" do
75
+ project = Project.create
76
+ lambda {
77
+ project.statuses.create(:name => 'Foo!')
78
+ }.should change { Status.count }
79
+ end
80
+
81
+ should "allow passing attributes" do
82
+ project = Project.create
83
+ status = project.statuses.create(:name => 'Foo!')
84
+ status.name.should == 'Foo!'
85
+ end
86
+
87
+ should "reset cache" do
88
+ project = Project.create
89
+ project.statuses.size.should == 0
90
+ project.statuses.create(:name => 'Foo!')
91
+ project.statuses.size.should == 1
92
+ end
93
+ end
94
+
95
+ context "create!" do
96
+ should "assign foreign key" do
97
+ project = Project.create
98
+ status = project.statuses.create!(:name => 'Foo!')
99
+ status.project_id.should == project.id
100
+ end
101
+
102
+ should "save record" do
103
+ project = Project.create
104
+ lambda {
105
+ project.statuses.create!(:name => 'Foo!')
106
+ }.should change { Status.count }
107
+ end
108
+
109
+ should "allow passing attributes" do
110
+ project = Project.create
111
+ status = project.statuses.create!(:name => 'Foo!')
112
+ status.name.should == 'Foo!'
113
+ end
114
+
115
+ should "raise exception if not valid" do
116
+ project = Project.create
117
+ lambda {
118
+ project.statuses.create!(:name => nil)
119
+ }.should raise_error(MongoMapper::DocumentNotValid)
120
+ end
121
+
122
+ should "reset cache" do
123
+ project = Project.create
124
+ project.statuses.size.should == 0
125
+ project.statuses.create!(:name => 'Foo!')
126
+ project.statuses.size.should == 1
127
+ end
128
+ end
129
+
130
+ context "count" do
131
+ should "work scoped to association" do
132
+ project = Project.create
133
+ 3.times { project.statuses.create(:name => 'Foo!') }
134
+
135
+ other_project = Project.create
136
+ 2.times { other_project.statuses.create(:name => 'Foo!') }
137
+
138
+ project.statuses.count.should == 3
139
+ other_project.statuses.count.should == 2
140
+ end
141
+
142
+ should "work with conditions" do
143
+ project = Project.create
144
+ project.statuses.create(:name => 'Foo')
145
+ project.statuses.create(:name => 'Other 1')
146
+ project.statuses.create(:name => 'Other 2')
147
+
148
+ project.statuses.count(:name => 'Foo').should == 1
149
+ end
150
+ end
151
+
152
+ context "Unassociating documents" do
153
+ setup do
154
+ @project = Project.create
155
+ @project.statuses << Status.create(:name => '1')
156
+ @project.statuses << Status.create(:name => '2')
157
+
158
+ @project2 = Project.create
159
+ @project2.statuses << Status.create(:name => '1')
160
+ @project2.statuses << Status.create(:name => '2')
161
+ end
162
+
163
+ should "work with destroy all" do
164
+ @project.statuses.count.should == 2
165
+ @project.statuses.destroy_all
166
+ @project.statuses.count.should == 0
167
+
168
+ @project2.statuses.count.should == 2
169
+ Status.count.should == 2
170
+ end
171
+
172
+ should "work with destroy all and conditions" do
173
+ @project.statuses.count.should == 2
174
+ @project.statuses.destroy_all(:name => '1')
175
+ @project.statuses.count.should == 1
176
+
177
+ @project2.statuses.count.should == 2
178
+ Status.count.should == 3
179
+ end
180
+
181
+ should "work with delete all" do
182
+ @project.statuses.count.should == 2
183
+ @project.statuses.delete_all
184
+ @project.statuses.count.should == 0
185
+
186
+ @project2.statuses.count.should == 2
187
+ Status.count.should == 2
188
+ end
189
+
190
+ should "work with delete all and conditions" do
191
+ @project.statuses.count.should == 2
192
+ @project.statuses.delete_all(:name => '1')
193
+ @project.statuses.count.should == 1
194
+
195
+ @project2.statuses.count.should == 2
196
+ Status.count.should == 3
197
+ end
198
+
199
+ should "work with nullify" do
200
+ @project.statuses.count.should == 2
201
+ @project.statuses.nullify
202
+ @project.statuses.count.should == 0
203
+
204
+ @project2.statuses.count.should == 2
205
+ Status.count.should == 4
206
+ Status.count(:name => '1').should == 2
207
+ Status.count(:name => '2').should == 2
208
+ end
209
+ end
210
+
211
+ context "Finding scoped to association" do
212
+ setup do
213
+ @project1 = Project.new(:name => 'Project 1')
214
+ @brand_new = Status.create(:name => 'New', :position => 1 )
215
+ @complete = Status.create(:name => 'Complete', :position => 2)
216
+ @project1.statuses = [@brand_new, @complete]
217
+ @project1.save
218
+
219
+ @project2 = Project.create(:name => 'Project 2')
220
+ @in_progress = Status.create(:name => 'In Progress')
221
+ @archived = Status.create(:name => 'Archived')
222
+ @another_complete = Status.create(:name => 'Complete')
223
+ @project2.statuses = [@in_progress, @archived, @another_complete]
224
+ @project2.save
225
+ end
226
+
227
+ context "dynamic finders" do
228
+ should "work with single key" do
229
+ @project1.statuses.find_by_name('New').should == @brand_new
230
+ @project1.statuses.find_by_name!('New').should == @brand_new
231
+ @project2.statuses.find_by_name('In Progress').should == @in_progress
232
+ @project2.statuses.find_by_name!('In Progress').should == @in_progress
233
+ end
234
+
235
+ should "work with multiple keys" do
236
+ @project1.statuses.find_by_name_and_position('New', 1).should == @brand_new
237
+ @project1.statuses.find_by_name_and_position!('New', 1).should == @brand_new
238
+ @project1.statuses.find_by_name_and_position('New', 2).should be_nil
239
+ end
240
+
241
+ should "raise error when using !" do
242
+ lambda {
243
+ @project1.statuses.find_by_name!('Fake')
244
+ }.should raise_error(MongoMapper::DocumentNotFound)
245
+ end
246
+
247
+ context "find_or_create_by" do
248
+ should "not create document if found" do
249
+ lambda {
250
+ status = @project1.statuses.find_or_create_by_name('New')
251
+ status.project.should == @project1
252
+ status.should == @brand_new
253
+ }.should_not change { Status.count }
254
+ end
255
+
256
+ should "create document if not found" do
257
+ lambda {
258
+ status = @project1.statuses.find_or_create_by_name('Delivered')
259
+ status.project.should == @project1
260
+ }.should change { Status.count }
261
+ end
262
+ end
263
+ end
264
+
265
+ context "all" do
266
+ should "work" do
267
+ @project1.statuses.all(:order => "position asc").should == [@brand_new, @complete]
268
+ end
269
+
270
+ should "work with conditions" do
271
+ @project1.statuses.all(:name => 'Complete').should == [@complete]
272
+ end
273
+ end
274
+
275
+ context "first" do
276
+ should "work" do
277
+ @project1.statuses.first(:order => 'name').should == @complete
278
+ end
279
+
280
+ should "work with conditions" do
281
+ @project1.statuses.first(:name => 'Complete').should == @complete
282
+ end
283
+ end
284
+
285
+ context "last" do
286
+ should "work" do
287
+ @project1.statuses.last(:order => "position asc").should == @complete
288
+ end
289
+
290
+ should "work with conditions" do
291
+ @project1.statuses.last(:order => 'position', :name => 'New').should == @brand_new
292
+ end
293
+ end
294
+
295
+ context "with one id" do
296
+ should "work for id in association" do
297
+ @project1.statuses.find(@complete.id).should == @complete
298
+ end
299
+
300
+ should "not work for id not in association" do
301
+ lambda {
302
+ @project1.statuses.find!(@archived.id)
303
+ }.should raise_error(MongoMapper::DocumentNotFound)
304
+ end
305
+ end
306
+
307
+ context "with multiple ids" do
308
+ should "work for ids in association" do
309
+ statuses = @project1.statuses.find(@brand_new.id, @complete.id)
310
+ statuses.should == [@brand_new, @complete]
311
+ end
312
+
313
+ should "not work for ids not in association" do
314
+ assert_raises(MongoMapper::DocumentNotFound) do
315
+ @project1.statuses.find!(@brand_new.id, @complete.id, @archived.id)
316
+ end
317
+ end
318
+ end
319
+
320
+ context "with #paginate" do
321
+ setup do
322
+ @statuses = @project2.statuses.paginate(:per_page => 2, :page => 1, :order => 'name asc')
323
+ end
324
+
325
+ should "return total pages" do
326
+ @statuses.total_pages.should == 2
327
+ end
328
+
329
+ should "return total entries" do
330
+ @statuses.total_entries.should == 3
331
+ end
332
+
333
+ should "return the subject" do
334
+ @statuses.collect(&:name).should == %w(Archived Complete)
335
+ end
336
+ end
337
+ end
338
+
339
+ context "extending the association" do
340
+ should "work using a block passed to many" do
341
+ project = Project.new(:name => "Some Project")
342
+ status1 = Status.new(:name => "New")
343
+ status2 = Status.new(:name => "Assigned")
344
+ status3 = Status.new(:name => "Closed")
345
+ project.statuses = [status1, status2, status3]
346
+ project.save
347
+
348
+ open_statuses = project.statuses.open
349
+ open_statuses.should include(status1)
350
+ open_statuses.should include(status2)
351
+ open_statuses.should_not include(status3)
352
+ end
353
+
354
+ should "work using many's :extend option" do
355
+ project = Project.new(:name => "Some Project")
356
+ collaborator1 = Collaborator.new(:name => "zing")
357
+ collaborator2 = Collaborator.new(:name => "zang")
358
+ project.collaborators = [collaborator1, collaborator2]
359
+ project.save
360
+ project.collaborators.top.should == collaborator1
361
+ end
362
+ end
363
+
364
+ context ":dependent" do
365
+ setup do
366
+ # FIXME: make use of already defined models
367
+ class ::Property
368
+ include MongoMapper::Document
369
+ end
370
+ Property.collection.remove
371
+
372
+ class ::Thing
373
+ include MongoMapper::Document
374
+ key :name, String
375
+ end
376
+ Thing.collection.remove
377
+ end
378
+
379
+ teardown do
380
+ Object.send :remove_const, 'Property' if defined?(::Property)
381
+ Object.send :remove_const, 'Thing' if defined?(::Thing)
382
+ end
383
+
384
+ context "=> destroy" do
385
+ setup do
386
+ Property.key :thing_id, ObjectId
387
+ Property.belongs_to :thing, :dependent => :destroy
388
+ Thing.many :properties, :dependent => :destroy
389
+
390
+ @thing = Thing.create(:name => "Tree")
391
+ @property1 = Property.create
392
+ @property2 = Property.create
393
+ @property3 = Property.create
394
+ @thing.properties << @property1
395
+ @thing.properties << @property2
396
+ @thing.properties << @property3
397
+ end
398
+
399
+ should "should destroy the associated documents" do
400
+ @thing.properties.count.should == 3
401
+ @thing.destroy
402
+ @thing.properties.count.should == 0
403
+ Property.count.should == 0
404
+ end
405
+ end
406
+
407
+ context "=> delete_all" do
408
+ setup do
409
+ Property.key :thing_id, ObjectId
410
+ Property.belongs_to :thing
411
+ Thing.has_many :properties, :dependent => :delete_all
412
+
413
+ @thing = Thing.create(:name => "Tree")
414
+ @property1 = Property.create
415
+ @property2 = Property.create
416
+ @property3 = Property.create
417
+ @thing.properties << @property1
418
+ @thing.properties << @property2
419
+ @thing.properties << @property3
420
+ end
421
+
422
+ should "should delete associated documents" do
423
+ @thing.properties.count.should == 3
424
+ @thing.destroy
425
+ @thing.properties.count.should == 0
426
+ Property.count.should == 0
427
+ end
428
+ end
429
+
430
+ context "=> nullify" do
431
+ setup do
432
+ Property.key :thing_id, ObjectId
433
+ Property.belongs_to :thing
434
+ Thing.has_many :properties, :dependent => :nullify
435
+
436
+ @thing = Thing.create(:name => "Tree")
437
+ @property1 = Property.create
438
+ @property2 = Property.create
439
+ @property3 = Property.create
440
+ @thing.properties << @property1
441
+ @thing.properties << @property2
442
+ @thing.properties << @property3
443
+ end
444
+
445
+ should "should nullify relationship but not destroy associated documents" do
446
+ @thing.properties.count.should == 3
447
+ @thing.destroy
448
+ @thing.properties.count.should == 0
449
+ Property.count.should == 3
450
+ end
451
+ end
452
+ end
453
+ end