tpitale-mongo_mapper 0.6.9 → 0.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) 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 +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_polymorphic_proxy.rb +8 -0
  25. data/test/functional/associations/test_belongs_to_proxy.rb +54 -9
  26. data/test/functional/associations/test_in_array_proxy.rb +309 -0
  27. data/test/functional/associations/test_many_documents_proxy.rb +103 -53
  28. data/test/functional/associations/test_many_embedded_proxy.rb +4 -14
  29. data/test/functional/associations/test_many_polymorphic_proxy.rb +4 -3
  30. data/test/functional/associations/test_one_proxy.rb +149 -0
  31. data/test/functional/test_binary.rb +13 -4
  32. data/test/functional/test_callbacks.rb +1 -5
  33. data/test/functional/test_dirty.rb +1 -4
  34. data/test/functional/test_document.rb +576 -640
  35. data/test/functional/test_embedded_document.rb +7 -20
  36. data/test/functional/test_modifiers.rb +238 -0
  37. data/test/functional/test_pagination.rb +1 -3
  38. data/test/functional/test_string_id_compatibility.rb +3 -8
  39. data/test/functional/test_validations.rb +13 -75
  40. data/test/models.rb +1 -1
  41. data/test/support/timing.rb +1 -1
  42. data/test/test_helper.rb +28 -0
  43. data/test/unit/associations/test_base.rb +54 -13
  44. data/test/unit/associations/test_proxy.rb +12 -0
  45. data/test/unit/test_document.rb +36 -26
  46. data/test/unit/test_embedded_document.rb +14 -51
  47. data/test/unit/test_finder_options.rb +36 -7
  48. data/test/unit/test_key.rb +1 -4
  49. data/test/unit/test_pagination.rb +6 -0
  50. data/test/unit/test_rails_compatibility.rb +4 -1
  51. data/test/unit/test_serializations.rb +1 -2
  52. data/test/unit/test_support.rb +4 -0
  53. data/test/unit/test_time_zones.rb +1 -2
  54. data/test/unit/test_validations.rb +3 -14
  55. metadata +12 -6
  56. data/lib/mongo_mapper/observing.rb +0 -50
  57. 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