mongo_mapper 0.6.8 → 0.6.9

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 (44) hide show
  1. data/README.rdoc +2 -17
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/mongo_mapper/associations/base.rb +19 -10
  5. data/lib/mongo_mapper/associations/in_array_proxy.rb +137 -0
  6. data/lib/mongo_mapper/associations/one_proxy.rb +61 -0
  7. data/lib/mongo_mapper/associations/proxy.rb +0 -2
  8. data/lib/mongo_mapper/associations.rb +5 -3
  9. data/lib/mongo_mapper/callbacks.rb +30 -78
  10. data/lib/mongo_mapper/dirty.rb +5 -24
  11. data/lib/mongo_mapper/document.rb +117 -144
  12. data/lib/mongo_mapper/embedded_document.rb +7 -11
  13. data/lib/mongo_mapper/finder_options.rb +42 -30
  14. data/lib/mongo_mapper/mongo_mapper.rb +125 -0
  15. data/lib/mongo_mapper/pagination.rb +12 -1
  16. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +1 -0
  17. data/lib/mongo_mapper/serialization.rb +2 -2
  18. data/lib/mongo_mapper/serializers/json_serializer.rb +2 -46
  19. data/lib/mongo_mapper/support.rb +5 -2
  20. data/lib/mongo_mapper/validations.rb +1 -3
  21. data/lib/mongo_mapper.rb +8 -2
  22. data/mongo_mapper.gemspec +14 -8
  23. data/specs.watchr +3 -5
  24. data/test/functional/associations/test_belongs_to_proxy.rb +43 -0
  25. data/test/functional/associations/test_in_array_proxy.rb +309 -0
  26. data/test/functional/associations/test_many_documents_proxy.rb +103 -53
  27. data/test/functional/associations/test_many_polymorphic_proxy.rb +4 -3
  28. data/test/functional/associations/test_one_proxy.rb +131 -0
  29. data/test/functional/test_binary.rb +15 -0
  30. data/test/functional/test_document.rb +581 -631
  31. data/test/functional/test_modifiers.rb +242 -0
  32. data/test/functional/test_validations.rb +0 -17
  33. data/test/models.rb +1 -1
  34. data/test/support/timing.rb +1 -1
  35. data/test/unit/associations/test_base.rb +54 -13
  36. data/test/unit/test_document.rb +32 -0
  37. data/test/unit/test_embedded_document.rb +0 -9
  38. data/test/unit/test_finder_options.rb +36 -7
  39. data/test/unit/test_pagination.rb +6 -0
  40. data/test/unit/test_rails_compatibility.rb +4 -1
  41. data/test/unit/test_support.rb +4 -0
  42. metadata +12 -6
  43. data/lib/mongo_mapper/observing.rb +0 -50
  44. data/test/unit/test_observing.rb +0 -101
@@ -0,0 +1,309 @@
1
+ require 'test_helper'
2
+
3
+ class InArrayProxyTest < Test::Unit::TestCase
4
+ context "description" do
5
+ setup do
6
+ class ::List
7
+ include MongoMapper::Document
8
+ key :name, String, :required => true
9
+ end
10
+
11
+ class ::User
12
+ include MongoMapper::Document
13
+ key :name, String, :required => true
14
+ key :list_ids, Array
15
+ many :lists, :in => :list_ids
16
+ end
17
+ User.collection.remove
18
+ List.collection.remove
19
+ end
20
+
21
+ teardown do
22
+ Object.send :remove_const, 'List' if defined?(::List)
23
+ Object.send :remove_const, 'User' if defined?(::User)
24
+ end
25
+
26
+ should "default reader to empty array" do
27
+ User.new.lists.should == []
28
+ end
29
+
30
+ should "allow adding to association like it was an array" do
31
+ user = User.new(:name => 'John')
32
+ user.lists << List.new(:name => 'Foo1!')
33
+ user.lists.push List.new(:name => 'Foo2!')
34
+ user.lists.concat List.new(:name => 'Foo3!')
35
+ user.lists.size.should == 3
36
+ end
37
+
38
+ should "ignore adding duplicate ids" do
39
+ user = User.create(:name => 'John')
40
+ list = List.create(:name => 'Foo')
41
+ user.lists << list
42
+ user.lists << list
43
+ user.lists << list
44
+
45
+ user.list_ids.should == [list.id]
46
+ user.lists.count.should == 1
47
+ end
48
+
49
+ should "be able to replace the association" do
50
+ user = User.new(:name => 'John')
51
+ list = List.new(:name => 'Foo')
52
+ user.lists = [list]
53
+ user.save.should be_true
54
+
55
+ user.reload
56
+ user.list_ids.should == [list.id]
57
+ user.lists.size.should == 1
58
+ user.lists[0].name.should == 'Foo'
59
+ end
60
+
61
+ context "create" do
62
+ setup do
63
+ @user = User.create(:name => 'John')
64
+ @list = @user.lists.create(:name => 'Foo!')
65
+ end
66
+
67
+ should "add id to key" do
68
+ @user.list_ids.should include(@list.id)
69
+ end
70
+
71
+ should "persist id addition to key in database" do
72
+ @user.reload
73
+ @user.list_ids.should include(@list.id)
74
+ end
75
+
76
+ should "add doc to association" do
77
+ @user.lists.should include(@list)
78
+ end
79
+
80
+ should "save doc" do
81
+ @list.should_not be_new
82
+ end
83
+ end
84
+
85
+ context "create!" do
86
+ setup do
87
+ @user = User.create(:name => 'John')
88
+ @list = @user.lists.create!(:name => 'Foo!')
89
+ end
90
+
91
+ should "add id to key" do
92
+ @user.list_ids.should include(@list.id)
93
+ end
94
+
95
+ should "persist id addition to key in database" do
96
+ @user.reload
97
+ @user.list_ids.should include(@list.id)
98
+ end
99
+
100
+ should "add doc to association" do
101
+ @user.lists.should include(@list)
102
+ end
103
+
104
+ should "save doc" do
105
+ @list.should_not be_new
106
+ end
107
+
108
+ should "raise exception if invalid" do
109
+ assert_raises(MongoMapper::DocumentNotValid) do
110
+ @user.lists.create!
111
+ end
112
+ end
113
+ end
114
+
115
+ context "Finding scoped to association" do
116
+ setup do
117
+ @user = User.create(:name => 'John')
118
+ @user2 = User.create(:name => 'Brandon')
119
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
120
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
121
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
122
+ end
123
+
124
+ context "all" do
125
+ should "work" do
126
+ @user.lists.find(:all, :order => :position.asc).should == [@list1, @list2]
127
+ @user.lists.all(:order => :position.asc).should == [@list1, @list2]
128
+ end
129
+
130
+ should "work with conditions" do
131
+ @user.lists.find(:all, :name => 'Foo 1').should == [@list1]
132
+ @user.lists.all(:name => 'Foo 1').should == [@list1]
133
+ end
134
+ end
135
+
136
+ context "first" do
137
+ should "work" do
138
+ @user.lists.find(:first, :order => 'position').should == @list1
139
+ @user.lists.first(:order => 'position').should == @list1
140
+ end
141
+
142
+ should "work with conditions" do
143
+ @user.lists.find(:first, :position => 2).should == @list2
144
+ @user.lists.first(:position => 2).should == @list2
145
+ end
146
+ end
147
+
148
+ context "last" do
149
+ should "work" do
150
+ @user.lists.find(:last, :order => 'position').should == @list2
151
+ @user.lists.last(:order => 'position').should == @list2
152
+ end
153
+
154
+ should "work with conditions" do
155
+ @user.lists.find(:last, :position => 2, :order => 'position').should == @list2
156
+ @user.lists.last(:position => 2, :order => 'position').should == @list2
157
+ end
158
+ end
159
+
160
+ context "with one id" do
161
+ should "work for id in association" do
162
+ @user.lists.find(@list1.id).should == @list1
163
+ end
164
+
165
+ should "not work for id not in association" do
166
+ @user.lists.find(@list3.id).should be_nil
167
+ end
168
+
169
+ should "raise error when using ! and not found" do
170
+ assert_raises MongoMapper::DocumentNotFound do
171
+ @user.lists.find!(@list3.id)
172
+ end
173
+ end
174
+ end
175
+
176
+ context "with multiple ids" do
177
+ should "work for ids in association" do
178
+ @user.lists.find(@list1.id, @list2.id).should == [@list1, @list2]
179
+ end
180
+
181
+ should "not work for ids not in association" do
182
+ @user.lists.find(@list1.id, @list2.id, @list3.id).should == [@list1, @list2]
183
+ end
184
+ end
185
+
186
+ context "with #paginate" do
187
+ setup do
188
+ @lists = @user.lists.paginate(:per_page => 1, :page => 1, :order => 'position')
189
+ end
190
+
191
+ should "return total pages" do
192
+ @lists.total_pages.should == 2
193
+ end
194
+
195
+ should "return total entries" do
196
+ @lists.total_entries.should == 2
197
+ end
198
+
199
+ should "return the subject" do
200
+ @lists.collect(&:name).should == ['Foo 1']
201
+ end
202
+ end
203
+
204
+ context "dynamic finders" do
205
+ should "work with single key" do
206
+ @user.lists.find_by_name('Foo 1').should == @list1
207
+ @user.lists.find_by_name!('Foo 1').should == @list1
208
+ @user.lists.find_by_name('Foo 3').should be_nil
209
+ end
210
+
211
+ should "work with multiple keys" do
212
+ @user.lists.find_by_name_and_position('Foo 1', 1).should == @list1
213
+ @user.lists.find_by_name_and_position!('Foo 1', 1).should == @list1
214
+ @user.lists.find_by_name_and_position('Foo 3', 1).should be_nil
215
+ end
216
+
217
+ should "raise error when using ! and not found" do
218
+ assert_raises(MongoMapper::DocumentNotFound) do
219
+ @user.lists.find_by_name!('Foo 3')
220
+ end
221
+ end
222
+
223
+ context "find_or_create_by" do
224
+ should "not create document if found" do
225
+ lambda {
226
+ list = @user.lists.find_or_create_by_name('Foo 1')
227
+ list.should == @list1
228
+ }.should_not change { List.count }
229
+ end
230
+
231
+ should "create document if not found" do
232
+ lambda {
233
+ list = @user.lists.find_or_create_by_name('Home')
234
+ @user.lists.should include(list)
235
+ }.should change { List.count }
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ context "count" do
242
+ setup do
243
+ @user = User.create(:name => 'John')
244
+ @user2 = User.create(:name => 'Brandon')
245
+ @list1 = @user.lists.create!(:name => 'Foo 1')
246
+ @list2 = @user.lists.create!(:name => 'Foo 2')
247
+ @list3 = @user2.lists.create!(:name => 'Foo 3')
248
+ end
249
+
250
+ should "return number of ids" do
251
+ @user.lists.count.should == 2
252
+ @user2.lists.count.should == 1
253
+ end
254
+
255
+ should "return correct count when given criteria" do
256
+ @user.lists.count(:name => 'Foo 1').should == 1
257
+ @user2.lists.count(:name => 'Foo 1').should == 0
258
+ end
259
+ end
260
+
261
+ context "Removing documents" do
262
+ setup do
263
+ @user = User.create(:name => 'John')
264
+ @user2 = User.create(:name => 'Brandon')
265
+ @list1 = @user.lists.create!(:name => 'Foo 1', :position => 1)
266
+ @list2 = @user.lists.create!(:name => 'Foo 2', :position => 2)
267
+ @list3 = @user2.lists.create!(:name => 'Foo 3', :position => 1)
268
+ end
269
+
270
+ context "destroy_all" do
271
+ should "work" do
272
+ @user.lists.count.should == 2
273
+ @user.lists.destroy_all
274
+ @user.lists.count.should == 0
275
+ end
276
+
277
+ should "work with conditions" do
278
+ @user.lists.count.should == 2
279
+ @user.lists.destroy_all(:name => 'Foo 1')
280
+ @user.lists.count.should == 1
281
+ end
282
+ end
283
+
284
+ context "delete_all" do
285
+ should "work" do
286
+ @user.lists.count.should == 2
287
+ @user.lists.delete_all
288
+ @user.lists.count.should == 0
289
+ end
290
+
291
+ should "work with conditions" do
292
+ @user.lists.count.should == 2
293
+ @user.lists.delete_all(:name => 'Foo 1')
294
+ @user.lists.count.should == 1
295
+ end
296
+ end
297
+
298
+ should "work with nullify" do
299
+ @user.lists.count.should == 2
300
+
301
+ lambda {
302
+ @user.lists.nullify
303
+ }.should_not change { List.count }
304
+
305
+ @user.lists.count.should == 0
306
+ end
307
+ end
308
+ end
309
+ end
@@ -22,10 +22,10 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
22
22
 
23
23
  should "be able to replace the association" do
24
24
  project = Project.new
25
- project.statuses = [Status.new("name" => "ready")]
25
+ project.statuses = [Status.new(:name => "ready")]
26
26
  project.save.should be_true
27
27
 
28
- project = project.reload
28
+ project.reload
29
29
  project.statuses.size.should == 1
30
30
  project.statuses[0].name.should == "ready"
31
31
  end
@@ -36,7 +36,7 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
36
36
  project.statuses.push Status.new(:name => 'push')
37
37
  project.statuses.concat Status.new(:name => 'concat')
38
38
 
39
- project = project.reload
39
+ project.reload
40
40
  project.statuses[0].project_id.should == project.id
41
41
  project.statuses[1].project_id.should == project.id
42
42
  project.statuses[2].project_id.should == project.id
@@ -235,84 +235,44 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
235
235
  lambda {
236
236
  status = @project1.statuses.find_or_create_by_name('Delivered')
237
237
  status.project.should == @project1
238
- }.should change { Status.count }.by(1)
238
+ }.should change { Status.count }
239
239
  end
240
240
  end
241
241
  end
242
242
 
243
- context "with :all" do
243
+ context "all" do
244
244
  should "work" do
245
245
  @project1.statuses.find(:all, :order => "position asc").should == [@brand_new, @complete]
246
- end
247
-
248
- should "work with conditions" do
249
- statuses = @project1.statuses.find(:all, :name => 'Complete')
250
- statuses.should == [@complete]
251
- end
252
-
253
- should "work with order" do
254
- statuses = @project1.statuses.find(:all, :order => 'name asc')
255
- statuses.should == [@complete, @brand_new]
256
- end
257
- end
258
-
259
- context "with #all" do
260
- should "work" do
261
246
  @project1.statuses.all(:order => "position asc").should == [@brand_new, @complete]
262
247
  end
263
248
 
264
249
  should "work with conditions" do
265
- statuses = @project1.statuses.all(:name => 'Complete')
266
- statuses.should == [@complete]
267
- end
268
-
269
- should "work with order" do
270
- statuses = @project1.statuses.all(:order => 'name asc')
271
- statuses.should == [@complete, @brand_new]
250
+ @project1.statuses.find(:all, :name => 'Complete').should == [@complete]
251
+ @project1.statuses.all(:name => 'Complete').should == [@complete]
272
252
  end
273
253
  end
274
254
 
275
- context "with :first" do
255
+ context "first" do
276
256
  should "work" do
277
257
  @project1.statuses.find(:first, :order => 'name').should == @complete
278
- end
279
-
280
- should "work with conditions" do
281
- status = @project1.statuses.find(:first, :name => 'Complete')
282
- status.should == @complete
283
- end
284
- end
285
-
286
- context "with #first" do
287
- should "work" do
288
258
  @project1.statuses.first(:order => 'name').should == @complete
289
259
  end
290
260
 
291
261
  should "work with conditions" do
292
- status = @project1.statuses.first(:name => 'Complete')
293
- status.should == @complete
262
+ @project1.statuses.find(:first, :name => 'Complete').should == @complete
263
+ @project1.statuses.first(:name => 'Complete').should == @complete
294
264
  end
295
265
  end
296
266
 
297
- context "with :last" do
267
+ context "last" do
298
268
  should "work" do
299
269
  @project1.statuses.find(:last, :order => "position asc").should == @complete
300
- end
301
-
302
- should "work with conditions" do
303
- status = @project1.statuses.find(:last, :order => 'position', :name => 'New')
304
- status.should == @brand_new
305
- end
306
- end
307
-
308
- context "with #last" do
309
- should "work" do
310
270
  @project1.statuses.last(:order => "position asc").should == @complete
311
271
  end
312
272
 
313
273
  should "work with conditions" do
314
- status = @project1.statuses.last(:order => 'position', :name => 'New')
315
- status.should == @brand_new
274
+ @project1.statuses.find(:last, :order => 'position', :name => 'New').should == @brand_new
275
+ @project1.statuses.last(:order => 'position', :name => 'New').should == @brand_new
316
276
  end
317
277
  end
318
278
 
@@ -384,4 +344,94 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
384
344
  project.collaborators.top.should == collaborator1
385
345
  end
386
346
  end
347
+
348
+ context ":dependent" do
349
+ setup do
350
+ # FIXME: make use of already defined models
351
+ class ::Property
352
+ include MongoMapper::Document
353
+ end
354
+ Property.collection.remove
355
+
356
+ class ::Thing
357
+ include MongoMapper::Document
358
+ key :name, String
359
+ end
360
+ Thing.collection.remove
361
+ end
362
+
363
+ teardown do
364
+ Object.send :remove_const, 'Property' if defined?(::Property)
365
+ Object.send :remove_const, 'Thing' if defined?(::Thing)
366
+ end
367
+
368
+ context "=> destroy" do
369
+ setup do
370
+ Property.key :thing_id, ObjectId
371
+ Property.belongs_to :thing, :dependent => :destroy
372
+ Thing.many :properties, :dependent => :destroy
373
+
374
+ @thing = Thing.create(:name => "Tree")
375
+ @property1 = Property.create
376
+ @property2 = Property.create
377
+ @property3 = Property.create
378
+ @thing.properties << @property1
379
+ @thing.properties << @property2
380
+ @thing.properties << @property3
381
+ end
382
+
383
+ should "should destroy the associated documents" do
384
+ @thing.properties.count.should == 3
385
+ @thing.destroy
386
+ @thing.properties.count.should == 0
387
+ Property.count.should == 0
388
+ end
389
+ end
390
+
391
+ context "=> delete_all" do
392
+ setup do
393
+ Property.key :thing_id, ObjectId
394
+ Property.belongs_to :thing
395
+ Thing.has_many :properties, :dependent => :delete_all
396
+
397
+ @thing = Thing.create(:name => "Tree")
398
+ @property1 = Property.create
399
+ @property2 = Property.create
400
+ @property3 = Property.create
401
+ @thing.properties << @property1
402
+ @thing.properties << @property2
403
+ @thing.properties << @property3
404
+ end
405
+
406
+ should "should delete associated documents" do
407
+ @thing.properties.count.should == 3
408
+ @thing.destroy
409
+ @thing.properties.count.should == 0
410
+ Property.count.should == 0
411
+ end
412
+ end
413
+
414
+ context "=> nullify" do
415
+ setup do
416
+ Property.key :thing_id, ObjectId
417
+ Property.belongs_to :thing
418
+ Thing.has_many :properties, :dependent => :nullify
419
+
420
+ @thing = Thing.create(:name => "Tree")
421
+ @property1 = Property.create
422
+ @property2 = Property.create
423
+ @property3 = Property.create
424
+ @thing.properties << @property1
425
+ @thing.properties << @property2
426
+ @thing.properties << @property3
427
+ end
428
+
429
+ should "should nullify relationship but not destroy associated documents" do
430
+ @thing.properties.count.should == 3
431
+ @thing.destroy
432
+ @thing.properties.count.should == 0
433
+ Property.count.should == 3
434
+ end
435
+ end
436
+ end
387
437
  end
@@ -134,8 +134,8 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
134
134
 
135
135
  @hall = Room.create(:name => 'Hall')
136
136
  @hm1 = Message.create(:body => 'Do not fall in the hall', :position => 1)
137
- @hm2 = Message.create(:body => 'Hall the king!', :position => 2)
138
137
  @hm3 = Message.create(:body => 'Loungin!', :position => 3)
138
+ @hm2 = Message.create(:body => 'Hall the king!', :position => 2)
139
139
  @hall.messages = [@hm1, @hm2, @hm3]
140
140
  @hall.save
141
141
  end
@@ -270,7 +270,7 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
270
270
  end
271
271
 
272
272
  should "allow overriding the order provided to the association" do
273
- @lounge.messages.all(:order => 'position desc').should == [@lm2, @lm1]
273
+ @lounge.messages.all(:order => 'position').should == [@lm1, @lm2]
274
274
  end
275
275
 
276
276
  should "allow using conditions on association" do
@@ -326,10 +326,11 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
326
326
  end
327
327
 
328
328
  should "work using many's :extend option" do
329
+
329
330
  room = Room.new(:name => "Amazing Room")
330
331
  accounts = room.accounts = [
331
332
  Bot.new(:last_logged_in => 3.weeks.ago),
332
- User.new(:last_logged_in => nil),
333
+ AccountUser.new(:last_logged_in => nil),
333
334
  Bot.new(:last_logged_in => 1.week.ago)
334
335
  ]
335
336
  room.save
@@ -0,0 +1,131 @@
1
+ require 'test_helper'
2
+
3
+ class OneProxyTest < Test::Unit::TestCase
4
+ def setup
5
+ @post_class = Class.new do
6
+ include MongoMapper::Document
7
+ def self.name; 'Post' end
8
+ end
9
+
10
+ @author_class = Class.new do
11
+ include MongoMapper::Document
12
+ key :post_id, ObjectId
13
+ end
14
+
15
+ @post_class.collection.remove
16
+ @author_class.collection.remove
17
+ end
18
+
19
+ should "default to nil" do
20
+ @post_class.one :author, :class => @author_class
21
+ @post_class.new.author.nil?.should be_true
22
+ end
23
+
24
+ should "be able to replace the association" do
25
+ @post_class.one :author, :class => @author_class
26
+ post = @post_class.new
27
+ author = @author_class.new
28
+ post.author = author
29
+ post.reload
30
+
31
+ post.author.should == author
32
+ post.author.nil?.should be_false
33
+ end
34
+
35
+ should "unset the association" do
36
+ @post_class.one :author, :class => @author_class
37
+ post = @post_class.new
38
+ author = @author_class.new
39
+ post.author = author
40
+ post.reload
41
+
42
+ post.author = nil
43
+ post.author.nil?.should be_false
44
+ end
45
+
46
+ should "work with :dependent delete" do
47
+ @post_class.one :author, :class => @author_class, :dependent => :delete
48
+
49
+ post = @post_class.create
50
+ author = @author_class.new
51
+ post.author = author
52
+ post.reload
53
+
54
+ @author_class.any_instance.expects(:delete).once
55
+ post.author = @author_class.new
56
+ end
57
+
58
+ should "work with :dependent destroy" do
59
+ @post_class.one :author, :class => @author_class, :dependent => :destroy
60
+
61
+ post = @post_class.create
62
+ author = @author_class.new
63
+ post.author = author
64
+ post.reload
65
+
66
+ @author_class.any_instance.expects(:destroy).once
67
+ post.author = @author_class.new
68
+ end
69
+
70
+ should "work with :dependent nullify" do
71
+ @post_class.one :author, :class => @author_class, :dependent => :nullify
72
+
73
+ post = @post_class.create
74
+ author = @author_class.new
75
+ post.author = author
76
+ post.reload
77
+
78
+ post.author = @author_class.new
79
+
80
+ author.reload
81
+ author.post_id.should be_nil
82
+ end
83
+
84
+ should "be able to build" do
85
+ @post_class.one :author, :class => @author_class
86
+
87
+ post = @post_class.create
88
+ author = post.author.build(:name => 'John')
89
+ post.author.should be_instance_of(@author_class)
90
+ post.author.should be_new
91
+ post.author.name.should == 'John'
92
+ post.author.should == author
93
+ post.author.post_id.should == post.id
94
+ end
95
+
96
+ should "be able to create" do
97
+ @post_class.one :author, :class => @author_class
98
+
99
+ post = @post_class.create
100
+ author = post.author.create(:name => 'John')
101
+ post.author.should be_instance_of(@author_class)
102
+ post.author.should_not be_new
103
+ post.author.name.should == 'John'
104
+ post.author.should == author
105
+ post.author.post_id.should == post.id
106
+ end
107
+
108
+ context "#create!" do
109
+ setup do
110
+ @author_class.key :name, String, :required => true
111
+ @post_class.one :author, :class => @author_class
112
+ end
113
+
114
+ should "raise exception if invalid" do
115
+ post = @post_class.create
116
+ assert_raises(MongoMapper::DocumentNotValid) do
117
+ post.author.create!
118
+ end
119
+ end
120
+
121
+ should "work if valid" do
122
+ post = @post_class.create
123
+ author = post.author.create!(:name => 'John')
124
+ post.author.should be_instance_of(@author_class)
125
+ post.author.should_not be_new
126
+ post.author.name.should == 'John'
127
+ post.author.should == author
128
+ post.author.post_id.should == post.id
129
+ end
130
+ end
131
+ end
@@ -15,4 +15,19 @@ class BinaryTest < Test::Unit::TestCase
15
15
  doc = doc.reload
16
16
  doc.contents.to_s.should == ByteBuffer.new('010101').to_s
17
17
  end
18
+
19
+ context "Saving a document with a blank binary value" do
20
+ setup do
21
+ @document = Class.new do
22
+ include MongoMapper::Document
23
+ set_collection_name 'test'
24
+ key :file, Binary
25
+ end
26
+ @document.collection.remove
27
+ end
28
+
29
+ should "not fail" do
30
+ assert_nothing_raised { @document.new(:file => nil).save }
31
+ end
32
+ end
18
33
  end