mongo_mapper 0.6.8 → 0.6.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README.rdoc +2 -17
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/mongo_mapper/associations/base.rb +19 -10
  5. data/lib/mongo_mapper/associations/in_array_proxy.rb +137 -0
  6. data/lib/mongo_mapper/associations/one_proxy.rb +61 -0
  7. data/lib/mongo_mapper/associations/proxy.rb +0 -2
  8. data/lib/mongo_mapper/associations.rb +5 -3
  9. data/lib/mongo_mapper/callbacks.rb +30 -78
  10. data/lib/mongo_mapper/dirty.rb +5 -24
  11. data/lib/mongo_mapper/document.rb +117 -144
  12. data/lib/mongo_mapper/embedded_document.rb +7 -11
  13. data/lib/mongo_mapper/finder_options.rb +42 -30
  14. data/lib/mongo_mapper/mongo_mapper.rb +125 -0
  15. data/lib/mongo_mapper/pagination.rb +12 -1
  16. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +1 -0
  17. data/lib/mongo_mapper/serialization.rb +2 -2
  18. data/lib/mongo_mapper/serializers/json_serializer.rb +2 -46
  19. data/lib/mongo_mapper/support.rb +5 -2
  20. data/lib/mongo_mapper/validations.rb +1 -3
  21. data/lib/mongo_mapper.rb +8 -2
  22. data/mongo_mapper.gemspec +14 -8
  23. data/specs.watchr +3 -5
  24. data/test/functional/associations/test_belongs_to_proxy.rb +43 -0
  25. data/test/functional/associations/test_in_array_proxy.rb +309 -0
  26. data/test/functional/associations/test_many_documents_proxy.rb +103 -53
  27. data/test/functional/associations/test_many_polymorphic_proxy.rb +4 -3
  28. data/test/functional/associations/test_one_proxy.rb +131 -0
  29. data/test/functional/test_binary.rb +15 -0
  30. data/test/functional/test_document.rb +581 -631
  31. data/test/functional/test_modifiers.rb +242 -0
  32. data/test/functional/test_validations.rb +0 -17
  33. data/test/models.rb +1 -1
  34. data/test/support/timing.rb +1 -1
  35. data/test/unit/associations/test_base.rb +54 -13
  36. data/test/unit/test_document.rb +32 -0
  37. data/test/unit/test_embedded_document.rb +0 -9
  38. data/test/unit/test_finder_options.rb +36 -7
  39. data/test/unit/test_pagination.rb +6 -0
  40. data/test/unit/test_rails_compatibility.rb +4 -1
  41. data/test/unit/test_support.rb +4 -0
  42. metadata +12 -6
  43. data/lib/mongo_mapper/observing.rb +0 -50
  44. data/test/unit/test_observing.rb +0 -101
@@ -14,759 +14,560 @@ class DocumentTest < Test::Unit::TestCase
14
14
  end
15
15
  @document.collection.remove
16
16
  end
17
-
18
- context "Saving a document with a custom id" do
19
- should "clear custom id flag when saved" do
20
- @document.key :_id, String
21
- doc = @document.new(:id => '1234')
22
- doc.using_custom_id?.should be_true
23
- doc.save.should be_true
24
- doc.using_custom_id?.should be_false
25
- end
26
- end
27
-
28
- context "Saving a document with a blank binary value" do
17
+
18
+ context "Using key with type Array" do
29
19
  setup do
30
- @document.key :file, Binary
20
+ @document.key :tags, Array
31
21
  end
32
22
 
33
- should "not fail" do
34
- doc = @document.new(:file => nil)
35
- lambda {
36
- doc.save
37
- }.should_not raise_error
23
+ should "give correct default" do
24
+ doc = @document.new
25
+ doc.tags.should == []
38
26
  end
39
- end
40
27
 
41
- context "Loading a document from the database with keys that are not defined" do
42
- setup do
43
- @id = Mongo::ObjectID.new
44
- @document.collection.insert({
45
- :_id => @id,
46
- :first_name => 'John',
47
- :last_name => 'Nunemaker',
48
- :age => 27,
49
- :favorite_color => 'red',
50
- :skills => ['ruby', 'rails', 'javascript', 'xhtml', 'css']
51
- })
28
+ should "work with assignment" do
29
+ doc = @document.new
30
+ doc.tags = %w(foo bar)
31
+ doc.tags.should == %w(foo bar)
52
32
  end
53
33
 
54
- should "assign all keys from database" do
55
- doc = @document.find(@id)
56
- doc.first_name.should == 'John'
57
- doc.last_name.should == 'Nunemaker'
58
- doc.age.should == 27
59
- doc.favorite_color.should == 'red'
60
- doc.skills.should == ['ruby', 'rails', 'javascript', 'xhtml', 'css']
34
+ should "work with assignment after saving" do
35
+ doc = @document.new
36
+ doc.tags = %w(foo bar)
37
+ doc.save
38
+ doc.tags.should == %w(foo bar)
39
+ doc.reload.tags.should == %w(foo bar)
61
40
  end
62
- end
63
-
64
- context "Document Class Methods" do
65
- context "Using key with type Array" do
66
- setup do
67
- @document.key :tags, Array
68
- end
69
-
70
- should "give correct default" do
71
- doc = @document.new
72
- doc.tags.should == []
73
- end
74
-
75
- should "work with assignment" do
76
- doc = @document.new
77
- doc.tags = %w(foo bar)
78
- doc.tags.should == %w(foo bar)
79
- end
80
-
81
- should "work with assignment after saving" do
82
- doc = @document.new
83
- doc.tags = %w(foo bar)
84
- doc.save
85
- doc.tags.should == %w(foo bar)
86
- doc.reload.tags.should == %w(foo bar)
87
- end
88
-
89
- should "work with assignment then <<" do
90
- doc = @document.new
91
- doc.tags = []
92
- doc.tags << "foo"
93
- doc.tags.should == ["foo"]
94
- end
95
41
 
96
- should "work with <<" do
97
- doc = @document.new
98
- doc.tags << "foo"
99
- doc.tags.should == ["foo"]
100
- end
101
-
102
- should "work with << then save" do
103
- doc = @document.new
104
- doc.tags << "foo"
105
- doc.tags << "bar"
106
- doc.save
107
- doc.tags.should == %w(foo bar)
108
- doc.reload.tags.should == %w(foo bar)
109
- end
42
+ should "work with assignment then <<" do
43
+ doc = @document.new
44
+ doc.tags = []
45
+ doc.tags << "foo"
46
+ doc.tags.should == ["foo"]
110
47
  end
111
48
 
112
- context "Using key with type Hash" do
113
- setup do
114
- @document.key :foo, Hash
115
- end
49
+ should "work with <<" do
50
+ doc = @document.new
51
+ doc.tags << "foo"
52
+ doc.tags.should == ["foo"]
53
+ end
116
54
 
117
- should "give correct default" do
118
- doc = @document.new
119
- doc.foo.should == {}
120
- end
55
+ should "work with << then save" do
56
+ doc = @document.new
57
+ doc.tags << "foo"
58
+ doc.tags << "bar"
59
+ doc.save
60
+ doc.tags.should == %w(foo bar)
61
+ doc.reload.tags.should == %w(foo bar)
62
+ end
63
+ end
121
64
 
122
- should "work with []=" do
123
- doc = @document.new
124
- doc.foo["quux"] = "bar"
125
- doc.foo["quux"].should == "bar"
126
- doc.foo.should == { "quux" => "bar" }
127
- end
65
+ context "Using key with type Hash" do
66
+ setup do
67
+ @document.key :foo, Hash
68
+ end
128
69
 
129
- should "work with indifferent access" do
130
- doc = @document.new
131
- doc.foo = {:baz => 'bar'}
132
- doc.foo[:baz].should == 'bar'
133
- doc.foo['baz'].should == 'bar'
134
- end
70
+ should "give correct default" do
71
+ doc = @document.new
72
+ doc.foo.should == {}
73
+ end
135
74
 
136
- should "work with indifferent access after save" do
137
- doc = @document.new
138
- doc.foo = {:baz => 'bar'}
139
- doc.save
75
+ should "work with []=" do
76
+ doc = @document.new
77
+ doc.foo["quux"] = "bar"
78
+ doc.foo["quux"].should == "bar"
79
+ doc.foo.should == { "quux" => "bar" }
80
+ end
140
81
 
141
- doc = doc.reload
142
- doc.foo[:baz].should == 'bar'
143
- doc.foo['baz'].should == 'bar'
144
- end
82
+ should "work with indifferent access" do
83
+ doc = @document.new
84
+ doc.foo = {:baz => 'bar'}
85
+ doc.foo[:baz].should == 'bar'
86
+ doc.foo['baz'].should == 'bar'
145
87
  end
146
88
 
147
- context "Using key with custom type with default" do
148
- setup do
149
- @document.key :window, WindowSize, :default => WindowSize.new(600, 480)
150
- end
89
+ should "work with indifferent access after save" do
90
+ doc = @document.new
91
+ doc.foo = {:baz => 'bar'}
92
+ doc.save
151
93
 
152
- should "default to default" do
153
- doc = @document.new
154
- doc.window.should == WindowSize.new(600, 480)
94
+ doc = doc.reload
95
+ doc.foo[:baz].should == 'bar'
96
+ doc.foo['baz'].should == 'bar'
97
+ end
98
+ end
155
99
 
156
- end
100
+ context "Using key with custom type with default" do
101
+ setup do
102
+ @document.key :window, WindowSize, :default => WindowSize.new(600, 480)
103
+ end
157
104
 
158
- should "save and load from mongo" do
159
- doc = @document.new
160
- doc.save
105
+ should "default to default" do
106
+ doc = @document.new
107
+ doc.window.should == WindowSize.new(600, 480)
161
108
 
162
- doc = doc.reload
163
- doc.window.should == WindowSize.new(600, 480)
164
- end
165
109
  end
166
110
 
167
- context "Creating a single document" do
168
- setup do
169
- @doc_instance = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
170
- end
171
-
172
- should "create a document in correct collection" do
173
- @document.count.should == 1
174
- end
111
+ should "save and load from mongo" do
112
+ doc = @document.new
113
+ doc.save
175
114
 
176
- should "automatically set id" do
177
- @doc_instance.id.should be_instance_of(Mongo::ObjectID)
178
- @doc_instance._id.should be_instance_of(Mongo::ObjectID)
179
- end
115
+ doc = doc.reload
116
+ doc.window.should == WindowSize.new(600, 480)
117
+ end
118
+ end
180
119
 
181
- should "no longer be new?" do
182
- @doc_instance.new?.should be_false
183
- end
120
+ context "ClassMethods#create (single document)" do
121
+ setup do
122
+ @doc_instance = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
123
+ end
184
124
 
185
- should "return instance of document" do
186
- @doc_instance.should be_instance_of(@document)
187
- @doc_instance.first_name.should == 'John'
188
- @doc_instance.last_name.should == 'Nunemaker'
189
- @doc_instance.age.should == 27
190
- end
125
+ should "create a document in correct collection" do
126
+ @document.count.should == 1
191
127
  end
192
128
 
193
- context "Creating a document with no attributes provided" do
194
- setup do
195
- @document = Class.new do
196
- include MongoMapper::Document
197
- set_collection_name 'test'
198
- end
199
- @document.collection.remove
200
- end
129
+ should "automatically set id" do
130
+ @doc_instance.id.should be_instance_of(Mongo::ObjectID)
131
+ @doc_instance._id.should be_instance_of(Mongo::ObjectID)
132
+ end
201
133
 
202
- should "create the document" do
203
- lambda {
204
- @document.create
205
- }.should change { @document.count }.by(1)
206
- end
134
+ should "no longer be new?" do
135
+ @doc_instance.new?.should be_false
207
136
  end
208
137
 
209
- context "Creating multiple documents" do
210
- setup do
211
- @doc_instances = @document.create([
212
- {:first_name => 'John', :last_name => 'Nunemaker', :age => '27'},
213
- {:first_name => 'Steve', :last_name => 'Smith', :age => '28'},
214
- ])
138
+ should "return instance of document" do
139
+ @doc_instance.should be_instance_of(@document)
140
+ @doc_instance.first_name.should == 'John'
141
+ @doc_instance.last_name.should == 'Nunemaker'
142
+ @doc_instance.age.should == 27
143
+ end
144
+
145
+ should "not fail if no attributes provided" do
146
+ document = Class.new do
147
+ include MongoMapper::Document
148
+ set_collection_name 'test'
215
149
  end
150
+ document.collection.remove
151
+
152
+ lambda { document.create }.should change { document.count }.by(1)
153
+ end
154
+ end
216
155
 
217
- should "create multiple documents" do
218
- @document.count.should == 2
219
- end
156
+ context "ClassMethods#create (multiple documents)" do
157
+ setup do
158
+ @doc_instances = @document.create([
159
+ {:first_name => 'John', :last_name => 'Nunemaker', :age => '27'},
160
+ {:first_name => 'Steve', :last_name => 'Smith', :age => '28'},
161
+ ])
162
+ end
220
163
 
221
- should "return an array of doc instances" do
222
- @doc_instances.map do |doc_instance|
223
- doc_instance.should be_instance_of(@document)
224
- end
225
- end
164
+ should "create multiple documents" do
165
+ @document.count.should == 2
226
166
  end
227
167
 
228
- context "Updating a document" do
229
- setup do
230
- doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
231
- @doc_instance = @document.update(doc._id, {:age => 40})
168
+ should "return an array of doc instances" do
169
+ @doc_instances.map do |doc_instance|
170
+ doc_instance.should be_instance_of(@document)
232
171
  end
172
+ end
173
+ end
233
174
 
234
- should "update attributes provided" do
235
- @doc_instance.age.should == 40
236
- end
175
+ context "ClassMethods#update (single document)" do
176
+ setup do
177
+ doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
178
+ @doc_instance = @document.update(doc._id, {:age => 40})
179
+ end
237
180
 
238
- should "not update existing attributes that were not set to update" do
239
- @doc_instance.first_name.should == 'John'
240
- @doc_instance.last_name.should == 'Nunemaker'
241
- end
181
+ should "update attributes provided" do
182
+ @doc_instance.age.should == 40
183
+ end
242
184
 
243
- should "not create new document" do
244
- @document.count.should == 1
245
- end
185
+ should "not update existing attributes that were not set to update" do
186
+ @doc_instance.first_name.should == 'John'
187
+ @doc_instance.last_name.should == 'Nunemaker'
246
188
  end
247
189
 
248
- should "raise error when updating single doc if not provided id and attributes" do
190
+ should "not create new document" do
191
+ @document.count.should == 1
192
+ end
193
+
194
+ should "raise error if not provided id" do
249
195
  doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
250
196
  lambda { @document.update }.should raise_error(ArgumentError)
197
+ end
198
+
199
+ should "raise error if not provided attributes" do
200
+ doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
251
201
  lambda { @document.update(doc._id) }.should raise_error(ArgumentError)
252
202
  lambda { @document.update(doc._id, [1]) }.should raise_error(ArgumentError)
253
203
  end
204
+ end
254
205
 
255
- context "Updating multiple documents" do
256
- setup do
257
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
258
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
259
-
260
- @doc_instances = @document.update({
261
- @doc1._id => {:age => 30},
262
- @doc2._id => {:age => 30},
263
- })
264
- end
206
+ context "ClassMethods#update (multiple documents)" do
207
+ setup do
208
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
209
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
265
210
 
266
- should "not create any new documents" do
267
- @document.count.should == 2
268
- end
211
+ @doc_instances = @document.update({
212
+ @doc1._id => {:age => 30},
213
+ @doc2._id => {:age => 30},
214
+ })
215
+ end
269
216
 
270
- should "should return an array of doc instances" do
271
- @doc_instances.map do |doc_instance|
272
- doc_instance.should be_instance_of(@document)
273
- end
274
- end
217
+ should "not create any new documents" do
218
+ @document.count.should == 2
219
+ end
275
220
 
276
- should "update the documents" do
277
- @document.find(@doc1._id).age.should == 30
278
- @document.find(@doc2._id).age.should == 30
221
+ should "should return an array of doc instances" do
222
+ @doc_instances.map do |doc_instance|
223
+ doc_instance.should be_instance_of(@document)
279
224
  end
280
225
  end
281
226
 
282
- should "raise error when updating multiple documents if not a hash" do
227
+ should "update the documents" do
228
+ @document.find(@doc1._id).age.should == 30
229
+ @document.find(@doc2._id).age.should == 30
230
+ end
231
+
232
+ should "raise error if not a hash" do
283
233
  lambda { @document.update([1, 2]) }.should raise_error(ArgumentError)
284
234
  end
235
+ end
285
236
 
286
- context "Finding documents" do
287
- setup do
288
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
289
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
290
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
291
- end
292
-
293
- should "return nil if nothing provided for find" do
294
- @document.find.should be_nil
295
- end
296
-
297
- should "raise document not found if nothing provided for find!" do
298
- lambda { @document.find! }.should raise_error(MongoMapper::DocumentNotFound)
299
- end
237
+ context "ClassMethods#find" do
238
+ setup do
239
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
240
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
241
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
242
+ end
300
243
 
301
- context "with a single id" do
302
- should "work" do
303
- @document.find(@doc1._id).should == @doc1
304
- end
244
+ should "return nil if nothing provided for find" do
245
+ @document.find.should be_nil
246
+ end
305
247
 
306
- should "return nil if document not found with find" do
307
- @document.find(123).should be_nil
308
- end
248
+ should "raise document not found if nothing provided for find!" do
249
+ lambda { @document.find! }.should raise_error(MongoMapper::DocumentNotFound)
250
+ end
309
251
 
310
- should "raise error if document not found with find!" do
311
- lambda {
312
- @document.find!(123)
313
- }.should raise_error(MongoMapper::DocumentNotFound)
314
- end
252
+ context "(with a single id)" do
253
+ should "work" do
254
+ @document.find(@doc1._id).should == @doc1
315
255
  end
316
256
 
317
- context "with multiple id's" do
318
- should "work as arguments" do
319
- @document.find(@doc1._id, @doc2._id).should == [@doc1, @doc2]
320
- end
321
-
322
- should "work as array" do
323
- @document.find([@doc1._id, @doc2._id]).should == [@doc1, @doc2]
324
- end
325
-
326
- should "return array if array only has one element" do
327
- @document.find([@doc1._id]).should == [@doc1]
328
- end
257
+ should "return nil if document not found with find" do
258
+ @document.find(123).should be_nil
329
259
  end
330
260
 
331
- should "be able to find using condition auto-detection" do
332
- @document.first(:first_name => 'John').should == @doc1
333
- @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
261
+ should "raise error if document not found with find!" do
262
+ lambda {
263
+ @document.find!(123)
264
+ }.should raise_error(MongoMapper::DocumentNotFound)
334
265
  end
266
+ end
335
267
 
336
- context "with :all" do
337
- should "find all documents" do
338
- @document.find(:all, :order => 'first_name').should == [@doc1, @doc3, @doc2]
339
- end
340
-
341
- should "be able to add conditions" do
342
- @document.find(:all, :first_name => 'John').should == [@doc1]
343
- end
268
+ context "(with multiple id's)" do
269
+ should "work as arguments" do
270
+ @document.find(@doc1._id, @doc2._id).should == [@doc1, @doc2]
344
271
  end
345
272
 
346
- context "with #all" do
347
- should "find all documents based on criteria" do
348
- @document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
349
- @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
350
- end
273
+ should "work as array" do
274
+ @document.find([@doc1._id, @doc2._id]).should == [@doc1, @doc2]
351
275
  end
352
276
 
353
- context "with :first" do
354
- should "find first document" do
355
- @document.find(:first, :order => 'first_name').should == @doc1
356
- end
277
+ should "return array if array only has one element" do
278
+ @document.find([@doc1._id]).should == [@doc1]
357
279
  end
280
+ end
358
281
 
359
- context "with #first" do
360
- should "find first document based on criteria" do
361
- @document.first(:order => 'first_name').should == @doc1
362
- @document.first(:age => 28).should == @doc2
363
- end
364
- end
282
+ should "be able to find using condition auto-detection" do
283
+ @document.first(:first_name => 'John').should == @doc1
284
+ @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
285
+ end
365
286
 
366
- context "with :last" do
367
- should "find last document" do
368
- @document.find(:last, :order => 'age').should == @doc2
369
- end
287
+ context "(with :all)" do
288
+ should "find all documents" do
289
+ @document.find(:all, :order => 'first_name').should == [@doc1, @doc3, @doc2]
370
290
  end
371
291
 
372
- context "with #last" do
373
- should "find last document based on criteria" do
374
- @document.last(:order => 'age').should == @doc2
375
- @document.last(:order => 'age', :age => 28).should == @doc2
376
- end
377
-
378
- should "raise error if no order provided" do
379
- lambda { @document.last() }.should raise_error
380
- end
292
+ should "be able to add conditions" do
293
+ @document.find(:all, :first_name => 'John').should == [@doc1]
381
294
  end
295
+ end
382
296
 
383
- context "with :find_by" do
384
- should "find document based on argument" do
385
- @document.find_by_first_name('John').should == @doc1
386
- @document.find_by_last_name('Nunemaker', :order => 'age desc').should == @doc1
387
- @document.find_by_age(27).should == @doc1
388
- end
389
-
390
- should "not raise error" do
391
- @document.find_by_first_name('Mongo').should be_nil
392
- end
297
+ context "(with #all)" do
298
+ should "find all documents based on criteria" do
299
+ @document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
300
+ @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
301
+ end
302
+ end
393
303
 
394
- should "define a method for each key" do
395
- @document.methods(false).select { |e| e =~ /^find_by_/ }.size == @document.keys.size
396
- end
304
+ context "(with :first)" do
305
+ should "find first document" do
306
+ @document.find(:first, :order => 'first_name').should == @doc1
397
307
  end
308
+ end
398
309
 
399
- context "with dynamic finders" do
400
- should "find document based on all arguments" do
401
- @document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 27).should == @doc1
402
- end
403
-
404
- should "not find the document if an argument is wrong" do
405
- @document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 28).should be_nil
406
- end
407
-
408
- should "find all documents based on arguments" do
409
- docs = @document.find_all_by_last_name('Nunemaker')
410
- docs.should be_kind_of(Array)
411
- docs.should include(@doc1)
412
- docs.should include(@doc3)
413
- end
414
-
415
- should "initialize document with given arguments" do
416
- doc = @document.find_or_initialize_by_first_name_and_last_name('David', 'Cuadrado')
417
- doc.should be_new
418
- doc.first_name.should == 'David'
419
- end
420
-
421
- should "not initialize document if document is found" do
422
- doc = @document.find_or_initialize_by_first_name('John')
423
- doc.should_not be_new
424
- end
425
-
426
- should "create document with given arguments" do
427
- doc = @document.find_or_create_by_first_name_and_last_name('David', 'Cuadrado')
428
- doc.should_not be_new
429
- doc.first_name.should == 'David'
430
- end
431
-
432
- should "raise error if document is not found when using !" do
433
- lambda {
434
- @document.find_by_first_name_and_last_name!(1,2)
435
- }.should raise_error(MongoMapper::DocumentNotFound)
436
- end
310
+ context "(with #first)" do
311
+ should "find first document based on criteria" do
312
+ @document.first(:order => 'first_name').should == @doc1
313
+ @document.first(:age => 28).should == @doc2
437
314
  end
438
- end # finding documents
315
+ end
439
316
 
440
- context "Finding document by id" do
441
- setup do
442
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
443
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
317
+ context "(with :last)" do
318
+ should "find last document" do
319
+ @document.find(:last, :order => 'age').should == @doc2
444
320
  end
321
+ end
445
322
 
446
- should "be able to find by id" do
447
- @document.find_by_id(@doc1._id).should == @doc1
448
- @document.find_by_id(@doc2._id).should == @doc2
323
+ context "(with #last)" do
324
+ should "find last document based on criteria" do
325
+ @document.last(:order => 'age').should == @doc2
326
+ @document.last(:order => 'age', :age => 28).should == @doc2
449
327
  end
450
328
 
451
- should "return nil if document not found" do
452
- @document.find_by_id(1234).should be(nil)
329
+ should "raise error if no order provided" do
330
+ lambda { @document.last() }.should raise_error
453
331
  end
454
332
  end
455
333
 
456
- context "Deleting a document" do
457
- setup do
458
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
459
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
460
- @document.delete(@doc1._id)
334
+ context "(with :find_by)" do
335
+ should "find document based on argument" do
336
+ @document.find_by_first_name('John').should == @doc1
337
+ @document.find_by_last_name('Nunemaker', :order => 'age desc').should == @doc1
338
+ @document.find_by_age(27).should == @doc1
461
339
  end
462
340
 
463
- should "remove document from collection" do
464
- @document.count.should == 1
341
+ should "not raise error" do
342
+ @document.find_by_first_name('Mongo').should be_nil
465
343
  end
466
344
 
467
- should "not remove other documents" do
468
- @document.find(@doc2._id).should_not be(nil)
345
+ should "define a method for each key" do
346
+ @document.methods(false).select { |e| e =~ /^find_by_/ }.size == @document.keys.size
469
347
  end
470
348
  end
471
349
 
472
- context "Deleting multiple documents" do
473
- should "work with multiple arguments" do
474
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
475
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
476
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
477
- @document.delete(@doc1._id, @doc2._id)
478
-
479
- @document.count.should == 1
350
+ context "(with dynamic finders)" do
351
+ should "find document based on all arguments" do
352
+ @document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 27).should == @doc1
480
353
  end
481
354
 
482
- should "work with array as argument" do
483
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
484
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
485
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
486
- @document.delete([@doc1._id, @doc2._id])
355
+ should "not find the document if an argument is wrong" do
356
+ @document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 28).should be_nil
357
+ end
487
358
 
488
- @document.count.should == 1
359
+ should "find all documents based on arguments" do
360
+ docs = @document.find_all_by_last_name('Nunemaker')
361
+ docs.should be_kind_of(Array)
362
+ docs.should include(@doc1)
363
+ docs.should include(@doc3)
489
364
  end
490
- end
491
365
 
492
- context "Deleting all documents" do
493
- setup do
494
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
495
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
496
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
366
+ should "initialize document with given arguments" do
367
+ doc = @document.find_or_initialize_by_first_name_and_last_name('David', 'Cuadrado')
368
+ doc.should be_new
369
+ doc.first_name.should == 'David'
497
370
  end
498
371
 
499
- should "remove all documents when given no conditions" do
500
- @document.delete_all
501
- @document.count.should == 0
372
+ should "not initialize document if document is found" do
373
+ doc = @document.find_or_initialize_by_first_name('John')
374
+ doc.should_not be_new
502
375
  end
503
376
 
504
- should "only remove matching documents when given conditions" do
505
- @document.delete_all({:first_name => 'John'})
506
- @document.count.should == 2
377
+ should "create document with given arguments" do
378
+ doc = @document.find_or_create_by_first_name_and_last_name('David', 'Cuadrado')
379
+ doc.should_not be_new
380
+ doc.first_name.should == 'David'
507
381
  end
508
382
 
509
- should "convert the conditions to mongo criteria" do
510
- @document.delete_all(:age => [26, 27])
511
- @document.count.should == 1
383
+ should "raise error if document is not found when using !" do
384
+ lambda {
385
+ @document.find_by_first_name_and_last_name!(1,2)
386
+ }.should raise_error(MongoMapper::DocumentNotFound)
512
387
  end
513
388
  end
389
+ end # finding documents
514
390
 
515
- context "Destroying a document" do
516
- setup do
517
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
518
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
519
- @document.destroy(@doc1._id)
520
- end
391
+ context "ClassMethods#find_by_id" do
392
+ setup do
393
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
394
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
395
+ end
521
396
 
522
- should "remove document from collection" do
523
- @document.count.should == 1
524
- end
397
+ should "be able to find by id" do
398
+ @document.find_by_id(@doc1._id).should == @doc1
399
+ @document.find_by_id(@doc2._id).should == @doc2
400
+ end
525
401
 
526
- should "not remove other documents" do
527
- @document.find(@doc2._id).should_not be(nil)
528
- end
402
+ should "return nil if document not found" do
403
+ @document.find_by_id(1234).should be(nil)
529
404
  end
405
+ end
530
406
 
531
- context "Destroying multiple documents" do
532
- should "work with multiple arguments" do
533
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
534
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
535
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
536
- @document.destroy(@doc1._id, @doc2._id)
537
-
538
- @document.count.should == 1
539
- end
407
+ context "ClassMethods#delete (single document)" do
408
+ setup do
409
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
410
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
411
+ @document.delete(@doc1._id)
412
+ end
540
413
 
541
- should "work with array as argument" do
542
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
543
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
544
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
545
- @document.destroy([@doc1._id, @doc2._id])
414
+ should "remove document from collection" do
415
+ @document.count.should == 1
416
+ end
546
417
 
547
- @document.count.should == 1
548
- end
418
+ should "not remove other documents" do
419
+ @document.find(@doc2._id).should_not be(nil)
549
420
  end
421
+ end
550
422
 
551
- context "Destroying all documents" do
552
- setup do
553
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
554
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
555
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
556
- end
423
+ context "ClassMethods#delete (multiple documents)" do
424
+ should "work with multiple arguments" do
425
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
426
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
427
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
428
+ @document.delete(@doc1._id, @doc2._id)
557
429
 
558
- should "remove all documents when given no conditions" do
559
- @document.destroy_all
560
- @document.count.should == 0
561
- end
430
+ @document.count.should == 1
431
+ end
562
432
 
563
- should "only remove matching documents when given conditions" do
564
- @document.destroy_all(:first_name => 'John')
565
- @document.count.should == 2
566
- @document.destroy_all(:age => 26)
567
- @document.count.should == 1
568
- end
433
+ should "work with array as argument" do
434
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
435
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
436
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
437
+ @document.delete([@doc1._id, @doc2._id])
569
438
 
570
- should "convert the conditions to mongo criteria" do
571
- @document.destroy_all(:age => [26, 27])
572
- @document.count.should == 1
573
- end
439
+ @document.count.should == 1
574
440
  end
441
+ end
575
442
 
576
- context ":dependent" do
577
- setup do
578
- # FIXME: make use of already defined models
579
- class ::Property
580
- include MongoMapper::Document
581
- end
582
- Property.collection.remove
443
+ context "ClassMethods#delete_all" do
444
+ setup do
445
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
446
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
447
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
448
+ end
583
449
 
584
- class ::Thing
585
- include MongoMapper::Document
586
- key :name, String
587
- end
588
- Thing.collection.remove
589
- end
450
+ should "remove all documents when given no conditions" do
451
+ @document.delete_all
452
+ @document.count.should == 0
453
+ end
590
454
 
591
- teardown do
592
- Object.send :remove_const, 'Property' if defined?(::Property)
593
- Object.send :remove_const, 'Thing' if defined?(::Thing)
594
- end
455
+ should "only remove matching documents when given conditions" do
456
+ @document.delete_all({:first_name => 'John'})
457
+ @document.count.should == 2
458
+ end
595
459
 
596
- context "many" do
597
- context "=> destroy" do
598
- setup do
599
- Property.key :thing_id, ObjectId
600
- Property.belongs_to :thing, :dependent => :destroy
601
- Thing.many :properties, :dependent => :destroy
602
-
603
- @thing = Thing.create(:name => "Tree")
604
- @property1 = Property.create
605
- @property2 = Property.create
606
- @property3 = Property.create
607
- @thing.properties << @property1
608
- @thing.properties << @property2
609
- @thing.properties << @property3
610
- end
611
-
612
- should "should destroy the associated documents" do
613
- @thing.properties.count.should == 3
614
- @thing.destroy
615
- @thing.properties.count.should == 0
616
- Property.count.should == 0
617
- end
618
- end
619
-
620
- context "=> delete_all" do
621
- setup do
622
- Property.key :thing_id, ObjectId
623
- Property.belongs_to :thing
624
- Thing.has_many :properties, :dependent => :delete_all
625
-
626
- @thing = Thing.create(:name => "Tree")
627
- @property1 = Property.create
628
- @property2 = Property.create
629
- @property3 = Property.create
630
- @thing.properties << @property1
631
- @thing.properties << @property2
632
- @thing.properties << @property3
633
- end
634
-
635
- should "should delete associated documents" do
636
- @thing.properties.count.should == 3
637
- @thing.destroy
638
- @thing.properties.count.should == 0
639
- Property.count.should == 0
640
- end
641
- end
642
-
643
- context "=> nullify" do
644
- setup do
645
- Property.key :thing_id, ObjectId
646
- Property.belongs_to :thing
647
- Thing.has_many :properties, :dependent => :nullify
648
-
649
- @thing = Thing.create(:name => "Tree")
650
- @property1 = Property.create
651
- @property2 = Property.create
652
- @property3 = Property.create
653
- @thing.properties << @property1
654
- @thing.properties << @property2
655
- @thing.properties << @property3
656
- end
657
-
658
- should "should nullify relationship but not destroy associated documents" do
659
- @thing.properties.count.should == 3
660
- @thing.destroy
661
- @thing.properties.count.should == 0
662
- Property.count.should == 3
663
- end
664
- end
665
- end
460
+ should "convert the conditions to mongo criteria" do
461
+ @document.delete_all(:age => [26, 27])
462
+ @document.count.should == 1
463
+ end
464
+ end
666
465
 
667
- context "belongs_to" do
668
- context "=> destroy" do
669
- setup do
670
- Property.key :thing_id, ObjectId
671
- Property.belongs_to :thing, :dependent => :destroy
672
- Thing.has_many :properties
673
-
674
- @thing = Thing.create(:name => "Tree")
675
- @property1 = Property.create
676
- @property2 = Property.create
677
- @property3 = Property.create
678
- @thing.properties << @property1
679
- @thing.properties << @property2
680
- @thing.properties << @property3
681
- end
682
-
683
- should "not execute on a belongs_to association" do
684
- Thing.count.should == 1
685
- @property1.destroy
686
- Thing.count.should == 1
687
- @property1.should be_frozen
688
- end
689
- end
690
- end
466
+ context "ClassMethods#destroy (single document)" do
467
+ setup do
468
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
469
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
470
+ @document.destroy(@doc1._id)
691
471
  end
692
472
 
693
- context "Counting documents in collection" do
694
- setup do
695
- @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
696
- @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
697
- @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
698
- end
473
+ should "remove document from collection" do
474
+ @document.count.should == 1
475
+ end
699
476
 
700
- should "count all with no arguments" do
701
- @document.count.should == 3
702
- end
477
+ should "not remove other documents" do
478
+ @document.find(@doc2._id).should_not be(nil)
479
+ end
480
+ end
703
481
 
704
- should "return 0 if there are no documents in the collection" do
705
- @document.delete_all
706
- @document.count.should == 0
707
- end
482
+ context "ClassMethods#destroy (multiple documents)" do
483
+ should "work with multiple arguments" do
484
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
485
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
486
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
487
+ @document.destroy(@doc1._id, @doc2._id)
488
+
489
+ @document.count.should == 1
490
+ end
708
491
 
709
- should "return 0 if the collection does not exist" do
710
- klass = Class.new do
711
- include MongoMapper::Document
712
- set_collection_name 'foobarbazwickdoesnotexist'
713
- end
714
- @document.collection.remove
492
+ should "work with array as argument" do
493
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
494
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
495
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
496
+ @document.destroy([@doc1._id, @doc2._id])
715
497
 
716
- klass.count.should == 0
717
- end
498
+ @document.count.should == 1
499
+ end
500
+ end
718
501
 
719
- should "return count for matching documents if conditions provided" do
720
- @document.count(:age => 27).should == 1
721
- end
502
+ context "ClassMethods#destroy_all" do
503
+ setup do
504
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
505
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
506
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
507
+ end
722
508
 
723
- should "convert the conditions to mongo criteria" do
724
- @document.count(:age => [26, 27]).should == 2
725
- end
509
+ should "remove all documents when given no conditions" do
510
+ @document.destroy_all
511
+ @document.count.should == 0
726
512
  end
727
513
 
728
- context "Indexing" do
729
- setup do
730
- @document.collection.drop_indexes
731
- end
514
+ should "only remove matching documents when given conditions" do
515
+ @document.destroy_all(:first_name => 'John')
516
+ @document.count.should == 2
517
+ @document.destroy_all(:age => 26)
518
+ @document.count.should == 1
519
+ end
732
520
 
733
- should "allow creating index for a key" do
734
- @document.ensure_index :first_name
735
- MongoMapper.ensure_indexes!
521
+ should "convert the conditions to mongo criteria" do
522
+ @document.destroy_all(:age => [26, 27])
523
+ @document.count.should == 1
524
+ end
525
+ end
736
526
 
737
- @document.should have_index('first_name_1')
738
- end
527
+ context "ClassMethods#count" do
528
+ setup do
529
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
530
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
531
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
532
+ end
739
533
 
740
- should "allow creating unique index for a key" do
741
- @document.ensure_index :first_name, :unique => true
742
- MongoMapper.ensure_indexes!
534
+ should "count all with no arguments" do
535
+ @document.count.should == 3
536
+ end
743
537
 
744
- @document.should have_index('first_name_1')
745
- end
538
+ should "return 0 if there are no documents in the collection" do
539
+ @document.delete_all
540
+ @document.count.should == 0
541
+ end
746
542
 
747
- should "allow creating index on multiple keys" do
748
- @document.ensure_index [[:first_name, 1], [:last_name, -1]]
749
- MongoMapper.ensure_indexes!
750
-
751
- # order is different for different versions of ruby so instead of
752
- # just checking have_index('first_name_1_last_name_-1') I'm checking
753
- # the values of the indexes to make sure the index creation was successful
754
- @document.collection.index_information.detect do |index|
755
- keys = index[1]
756
- keys.include?(['first_name', 1]) && keys.include?(['last_name', -1])
757
- end.should_not be_nil
543
+ should "return 0 if the collection does not exist" do
544
+ klass = Class.new do
545
+ include MongoMapper::Document
546
+ set_collection_name 'foobarbazwickdoesnotexist'
758
547
  end
548
+ @document.collection.remove
759
549
 
760
- should "work with :index shortcut when defining key" do
761
- @document.key :father, String, :index => true
762
- MongoMapper.ensure_indexes!
550
+ klass.count.should == 0
551
+ end
763
552
 
764
- @document.should have_index('father_1')
765
- end
553
+ should "return count for matching documents if conditions provided" do
554
+ @document.count(:age => 27).should == 1
555
+ end
556
+
557
+ should "convert the conditions to mongo criteria" do
558
+ @document.count(:age => [26, 27]).should == 2
766
559
  end
767
- end # Document Class Methods
560
+ end
561
+
562
+ should "have instance method for collection" do
563
+ @document.new.collection.name.should == @document.collection.name
564
+ end
565
+
566
+ should "have instance method for database" do
567
+ @document.new.database.should == @document.database
568
+ end
768
569
 
769
- context "Saving a new document" do
570
+ context "#save (new document)" do
770
571
  setup do
771
572
  @doc = @document.new(:first_name => 'John', :age => '27')
772
573
  @doc.save
@@ -815,7 +616,7 @@ class DocumentTest < Test::Unit::TestCase
815
616
  end
816
617
  end
817
618
 
818
- context "Saving an existing document" do
619
+ context "#save (existing document)" do
819
620
  setup do
820
621
  @doc = @document.create(:first_name => 'John', :age => '27')
821
622
  @doc.first_name = 'Johnny'
@@ -846,7 +647,7 @@ class DocumentTest < Test::Unit::TestCase
846
647
  end
847
648
  end
848
649
 
849
- context "Calling update attributes on a new document" do
650
+ context "#update_attributes (new document)" do
850
651
  setup do
851
652
  @doc = @document.new(:first_name => 'John', :age => '27')
852
653
  @doc.update_attributes(:first_name => 'Johnny', :age => 30)
@@ -878,7 +679,7 @@ class DocumentTest < Test::Unit::TestCase
878
679
  end
879
680
  end
880
681
 
881
- context "Updating an existing document using update attributes" do
682
+ context "#update_attributes (existing document)" do
882
683
  setup do
883
684
  @doc = @document.create(:first_name => 'John', :age => '27')
884
685
  @doc.update_attributes(:first_name => 'Johnny', :age => 30)
@@ -900,7 +701,7 @@ class DocumentTest < Test::Unit::TestCase
900
701
  end
901
702
  end
902
703
 
903
- context "update_attributes" do
704
+ context "#update_attributes" do
904
705
  setup do
905
706
  @document.key :foo, String, :required => true
906
707
  end
@@ -913,8 +714,56 @@ class DocumentTest < Test::Unit::TestCase
913
714
  @document.new.update_attributes({}).should be_false
914
715
  end
915
716
  end
717
+
718
+ context "#save (with validations off)" do
719
+ setup do
720
+ @document = Class.new do
721
+ include MongoMapper::Document
722
+ set_collection_name 'test'
723
+ key :name, String, :required => true
724
+ end
725
+ @document.collection.remove
726
+ end
916
727
 
917
- context "Destroying a document that exists" do
728
+ should "insert document" do
729
+ doc = @document.new
730
+ doc.save(:validate => false)
731
+ @document.count.should == 1
732
+ end
733
+
734
+ should "work with false passed to save" do
735
+ doc = @document.new
736
+ doc.save(false)
737
+ @document.count.should == 1
738
+ end
739
+ end
740
+
741
+ context "#save (with options)" do
742
+ setup do
743
+ MongoMapper.ensured_indexes = []
744
+
745
+ @document = Class.new do
746
+ include MongoMapper::Document
747
+ set_collection_name 'test'
748
+ key :name, String
749
+ ensure_index :name, :unique => true
750
+ end
751
+ @document.collection.drop_indexes
752
+
753
+ MongoMapper.ensure_indexes!
754
+ end
755
+
756
+ should "allow passing safe" do
757
+ doc = @document.new(:name => 'John')
758
+ doc.save
759
+
760
+ assert_raises(Mongo::OperationFailure) do
761
+ @document.new(:name => 'John').save(:safe => true)
762
+ end
763
+ end
764
+ end
765
+
766
+ context "#destroy" do
918
767
  setup do
919
768
  @doc = @document.create(:first_name => 'John', :age => '27')
920
769
  @doc.destroy
@@ -923,30 +772,35 @@ class DocumentTest < Test::Unit::TestCase
923
772
  should "remove the document from the collection" do
924
773
  @document.count.should == 0
925
774
  end
926
-
927
- should "raise error if assignment is attempted" do
928
- lambda { @doc.first_name = 'Foo' }.should raise_error(TypeError)
929
- end
930
-
931
- should "do nothing if destroy is called again" do
932
- @doc.destroy.should be_false
933
- end
934
775
  end
935
-
936
- context "Destroying a document that is a new" do
776
+
777
+ context "#delete" do
937
778
  setup do
938
- setup do
939
- @doc = @document.new(:first_name => 'John Nunemaker', :age => '27')
940
- @doc.destroy
941
- end
942
-
943
- should "not affect collection count" do
944
- @document.collection.count.should == 0
779
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
780
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
781
+
782
+ @document.class_eval do
783
+ before_destroy :before_destroy_callback
784
+ after_destroy :after_destroy_callback
785
+
786
+ def history; @history ||= [] end
787
+ def before_destroy_callback; history << :after_destroy end
788
+ def after_destroy_callback; history << :after_destroy end
945
789
  end
790
+
791
+ @doc1.delete
792
+ end
946
793
 
947
- should "raise error if assignment is attempted" do
948
- lambda { @doc.first_name = 'Foo' }.should raise_error(TypeError)
949
- end
794
+ should "remove document from collection" do
795
+ @document.count.should == 1
796
+ end
797
+
798
+ should "not remove other documents" do
799
+ @document.find(@doc2.id).should_not be(nil)
800
+ end
801
+
802
+ should "not call before/after destroy callbacks" do
803
+ @doc1.history.should == []
950
804
  end
951
805
  end
952
806
 
@@ -1164,6 +1018,28 @@ class DocumentTest < Test::Unit::TestCase
1164
1018
  end
1165
1019
  end
1166
1020
 
1021
+ context "userstamping" do
1022
+ setup do
1023
+ @document.userstamps!
1024
+ end
1025
+
1026
+ should "add creator_id key" do
1027
+ @document.keys.keys.should include('creator_id')
1028
+ end
1029
+
1030
+ should "add updater_id key" do
1031
+ @document.keys.keys.should include('updater_id')
1032
+ end
1033
+
1034
+ should "add belongs_to creator" do
1035
+ @document.associations.keys.should include('creator')
1036
+ end
1037
+
1038
+ should "add belongs_to updater" do
1039
+ @document.associations.keys.should include('updater')
1040
+ end
1041
+ end
1042
+
1167
1043
  context "#exist?" do
1168
1044
  setup do
1169
1045
  @doc = @document.create(:first_name => "James", :age => 27)
@@ -1187,7 +1063,7 @@ class DocumentTest < Test::Unit::TestCase
1187
1063
  end
1188
1064
  end
1189
1065
 
1190
- context "reload" do
1066
+ context "#reload" do
1191
1067
  setup do
1192
1068
  @foo_class = Class.new do
1193
1069
  include MongoMapper::Document
@@ -1232,4 +1108,78 @@ class DocumentTest < Test::Unit::TestCase
1232
1108
  @instance.reload.object_id.should == @instance.object_id
1233
1109
  end
1234
1110
  end
1111
+
1112
+ context "Saving a document with a custom id" do
1113
+ should "clear custom id flag when saved" do
1114
+ @document.key :_id, String
1115
+ doc = @document.new(:id => '1234')
1116
+ doc.using_custom_id?.should be_true
1117
+ doc.save.should be_true
1118
+ doc.using_custom_id?.should be_false
1119
+ end
1120
+ end
1121
+
1122
+ context "Loading a document from the database with keys that are not defined" do
1123
+ setup do
1124
+ @id = Mongo::ObjectID.new
1125
+ @document.collection.insert({
1126
+ :_id => @id,
1127
+ :first_name => 'John',
1128
+ :last_name => 'Nunemaker',
1129
+ :age => 27,
1130
+ :favorite_color => 'red',
1131
+ :skills => ['ruby', 'rails', 'javascript', 'xhtml', 'css']
1132
+ })
1133
+ end
1134
+
1135
+ should "assign all keys from database" do
1136
+ doc = @document.find(@id)
1137
+ doc.first_name.should == 'John'
1138
+ doc.last_name.should == 'Nunemaker'
1139
+ doc.age.should == 27
1140
+ doc.favorite_color.should == 'red'
1141
+ doc.skills.should == ['ruby', 'rails', 'javascript', 'xhtml', 'css']
1142
+ end
1143
+ end
1144
+
1145
+ context "Indexing" do
1146
+ setup do
1147
+ MongoMapper.ensured_indexes = []
1148
+ @document.collection.drop_indexes
1149
+ end
1150
+
1151
+ should "allow creating index for a key" do
1152
+ @document.ensure_index :first_name
1153
+ MongoMapper.ensure_indexes!
1154
+
1155
+ @document.should have_index('first_name_1')
1156
+ end
1157
+
1158
+ should "allow creating unique index for a key" do
1159
+ @document.ensure_index :first_name, :unique => true
1160
+ MongoMapper.ensure_indexes!
1161
+
1162
+ @document.should have_index('first_name_1')
1163
+ end
1164
+
1165
+ should "allow creating index on multiple keys" do
1166
+ @document.ensure_index [[:first_name, 1], [:last_name, -1]]
1167
+ MongoMapper.ensure_indexes!
1168
+
1169
+ # order is different for different versions of ruby so instead of
1170
+ # just checking have_index('first_name_1_last_name_-1') I'm checking
1171
+ # the values of the indexes to make sure the index creation was successful
1172
+ @document.collection.index_information.detect do |index|
1173
+ keys = index[1]
1174
+ keys.include?(['first_name', 1]) && keys.include?(['last_name', -1])
1175
+ end.should_not be_nil
1176
+ end
1177
+
1178
+ should "work with :index shortcut when defining key" do
1179
+ @document.key :father, String, :index => true
1180
+ MongoMapper.ensure_indexes!
1181
+
1182
+ @document.should have_index('father_1')
1183
+ end
1184
+ end
1235
1185
  end