mongo_mapper-unstable 2009.12.30 → 2010.1.4

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