mongoid 0.2.5
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.
- data/.gitignore +5 -0
- data/History.txt +2 -0
- data/MIT_LICENSE +20 -0
- data/README.textile +135 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/mongoid.rb +79 -0
- data/lib/mongoid/associations/association_factory.rb +21 -0
- data/lib/mongoid/associations/belongs_to_association.rb +23 -0
- data/lib/mongoid/associations/has_many_association.rb +36 -0
- data/lib/mongoid/associations/has_one_association.rb +35 -0
- data/lib/mongoid/document.rb +208 -0
- data/lib/mongoid/extensions.rb +7 -0
- data/lib/mongoid/extensions/array/conversions.rb +13 -0
- data/lib/mongoid/extensions/object/conversions.rb +13 -0
- data/lib/mongoid/paginator.rb +22 -0
- data/mongoid.gemspec +80 -0
- data/spec/integration/mongoid/document_spec.rb +95 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/unit/mongoid/associations/association_factory_spec.rb +48 -0
- data/spec/unit/mongoid/associations/belongs_to_association_spec.rb +35 -0
- data/spec/unit/mongoid/associations/has_many_association_spec.rb +126 -0
- data/spec/unit/mongoid/associations/has_one_association_spec.rb +35 -0
- data/spec/unit/mongoid/document_spec.rb +680 -0
- data/spec/unit/mongoid/extensions/array/conversions_spec.rb +14 -0
- data/spec/unit/mongoid/extensions/object/conversions_spec.rb +13 -0
- data/spec/unit/mongoid/paginator_spec.rb +74 -0
- metadata +110 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "/../../../spec_helper.rb")
|
2
|
+
|
3
|
+
describe Mongoid::Associations::HasOneAssociation do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@attributes = { :name => { :first_name => "Drexel" } }
|
7
|
+
@document = stub(:attributes => @attributes)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#method_missing" do
|
11
|
+
|
12
|
+
before do
|
13
|
+
@association = Mongoid::Associations::HasOneAssociation.new(:name, @document)
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when getting values" do
|
17
|
+
|
18
|
+
it "delegates to the document" do
|
19
|
+
@association.first_name.should == "Drexel"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when setting values" do
|
25
|
+
|
26
|
+
it "delegates to the document" do
|
27
|
+
@association.first_name = "Test"
|
28
|
+
@association.first_name.should == "Test"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,680 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "/../../spec_helper.rb")
|
2
|
+
|
3
|
+
describe Mongoid::Document do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@collection = mock
|
7
|
+
@database = stub(:collection => @collection)
|
8
|
+
Mongoid.stubs(:database).returns(@database)
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
Person.instance_variable_set(:@collection, nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#belongs_to" do
|
16
|
+
|
17
|
+
it "adds a new Association to the collection" do
|
18
|
+
address = Address.new
|
19
|
+
address.person.should_not be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "creates a reader for the association" do
|
23
|
+
address = Address.new
|
24
|
+
address.should respond_to(:person)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "creates a writer for the association" do
|
28
|
+
address = Address.new
|
29
|
+
address.should respond_to(:person=)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#collection" do
|
35
|
+
|
36
|
+
it "sets the collection name to the class pluralized" do
|
37
|
+
@database.expects(:collection).with("people").returns(@collection)
|
38
|
+
Person.collection
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#create" do
|
44
|
+
|
45
|
+
context "with no attributes" do
|
46
|
+
|
47
|
+
it "creates a new saved document" do
|
48
|
+
@collection.expects(:save).with({})
|
49
|
+
person = Person.create
|
50
|
+
person.should_not be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with attributes" do
|
56
|
+
|
57
|
+
it "creates a new saved document" do
|
58
|
+
@collection.expects(:save).with({:test => "test"})
|
59
|
+
person = Person.create(:test => "test")
|
60
|
+
person.should_not be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#destroy" do
|
68
|
+
|
69
|
+
context "when the Document is remove from the database" do
|
70
|
+
|
71
|
+
it "returns nil" do
|
72
|
+
id = Mongo::ObjectID.new
|
73
|
+
@collection.expects(:remove).with(:_id => id)
|
74
|
+
person = Person.new(:_id => id)
|
75
|
+
person.destroy.should be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#fields" do
|
83
|
+
|
84
|
+
before do
|
85
|
+
Person.fields([:testing])
|
86
|
+
end
|
87
|
+
|
88
|
+
it "adds a reader for the fields defined" do
|
89
|
+
@person = Person.new(:testing => "Test")
|
90
|
+
@person.testing.should == "Test"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "adds a writer for the fields defined" do
|
94
|
+
@person = Person.new(:testing => "Test")
|
95
|
+
@person.testing = "Testy"
|
96
|
+
@person.testing.should == "Testy"
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#find" do
|
102
|
+
|
103
|
+
before do
|
104
|
+
@attributes = { :document_class => "Person" }
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when an id is passed in" do
|
108
|
+
|
109
|
+
before do
|
110
|
+
@id = Mongo::ObjectID.new
|
111
|
+
end
|
112
|
+
|
113
|
+
it "delegates to find_first" do
|
114
|
+
@collection.expects(:find_one).with(Mongo::ObjectID.from_string(@id.to_s)).returns(@attributes)
|
115
|
+
Person.find(@id.to_s)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when finding first" do
|
121
|
+
|
122
|
+
it "delegates to find_first" do
|
123
|
+
@collection.expects(:find_one).with(:test => "Test" ).returns(@attributes)
|
124
|
+
Person.find(:first, :conditions => { :test => "Test" })
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when finding all" do
|
130
|
+
|
131
|
+
before do
|
132
|
+
@cursor = mock
|
133
|
+
@people = []
|
134
|
+
end
|
135
|
+
|
136
|
+
it "delegates to find_all" do
|
137
|
+
@collection.expects(:find).with(:test => "Test").returns(@cursor)
|
138
|
+
@cursor.expects(:collect).returns(@people)
|
139
|
+
Person.find(:all, :conditions => { :test => "Test" })
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#find_first" do
|
147
|
+
|
148
|
+
before do
|
149
|
+
@attributes = { :document_class => "Person" }
|
150
|
+
end
|
151
|
+
|
152
|
+
context "when a selector is provided" do
|
153
|
+
|
154
|
+
it "finds the first document from the collection and instantiates it" do
|
155
|
+
@collection.expects(:find_one).with(:test => "Test").returns(@attributes)
|
156
|
+
Person.find_first(:test => "Test").attributes.should == @attributes
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
context "when a selector is not provided" do
|
162
|
+
|
163
|
+
it "finds the first document from the collection and instantiates it" do
|
164
|
+
@collection.expects(:find_one).with(nil).returns(@attributes)
|
165
|
+
Person.find_first.attributes.should == @attributes
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#find_all" do
|
173
|
+
|
174
|
+
before do
|
175
|
+
@cursor = mock
|
176
|
+
@people = []
|
177
|
+
end
|
178
|
+
|
179
|
+
context "when a selector is provided" do
|
180
|
+
|
181
|
+
it "finds from the collection and instantiate objects for each returned" do
|
182
|
+
@collection.expects(:find).with(:test => "Test").returns(@cursor)
|
183
|
+
@cursor.expects(:collect).returns(@people)
|
184
|
+
Person.find_all(:test => "Test")
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
context "when a selector is not provided" do
|
190
|
+
|
191
|
+
it "finds from the collection and instantiate objects for each returned" do
|
192
|
+
@collection.expects(:find).with(nil).returns(@cursor)
|
193
|
+
@cursor.expects(:collect).returns(@people)
|
194
|
+
Person.find_all
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "#group_by" do
|
202
|
+
|
203
|
+
before do
|
204
|
+
@reduce = "function(obj, prev) { prev.group.push(obj); }"
|
205
|
+
end
|
206
|
+
|
207
|
+
it "returns documents grouped by the supplied fields" do
|
208
|
+
results = [{ "title" => "Sir", "group" => [{ "title" => "Sir", "age" => 30 }] }]
|
209
|
+
@collection.expects(:group).with([:title], {}, { :group => [] }, @reduce).returns(results)
|
210
|
+
grouped = Person.group_by([:title], {})
|
211
|
+
people = grouped.first["group"]
|
212
|
+
people.first.should be_a_kind_of(Person)
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "#has_many" do
|
218
|
+
|
219
|
+
it "adds a new Association to the collection" do
|
220
|
+
person = Person.new
|
221
|
+
person.addresses.should_not be_nil
|
222
|
+
end
|
223
|
+
|
224
|
+
it "creates a reader for the association" do
|
225
|
+
person = Person.new
|
226
|
+
person.should respond_to(:addresses)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "creates a writer for the association" do
|
230
|
+
person = Person.new
|
231
|
+
person.should respond_to(:addresses=)
|
232
|
+
end
|
233
|
+
|
234
|
+
context "when setting the association directly" do
|
235
|
+
|
236
|
+
before do
|
237
|
+
@attributes = { :title => "Sir",
|
238
|
+
:addresses => [
|
239
|
+
{ :street => "Street 1", :document_class => "Address" },
|
240
|
+
{ :street => "Street 2", :document_class => "Address" } ] }
|
241
|
+
@person = Person.new(@attributes)
|
242
|
+
end
|
243
|
+
|
244
|
+
it "sets the attributes for the association" do
|
245
|
+
address = Address.new(:street => "New Street", :document_class => "Address")
|
246
|
+
@person.addresses = [address]
|
247
|
+
@person.addresses.first.street.should == "New Street"
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "#has_one" do
|
255
|
+
|
256
|
+
it "adds a new Association to the collection" do
|
257
|
+
person = Person.new
|
258
|
+
person.name.should_not be_nil
|
259
|
+
end
|
260
|
+
|
261
|
+
it "creates a reader for the association" do
|
262
|
+
person = Person.new
|
263
|
+
person.should respond_to(:name)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "creates a writer for the association" do
|
267
|
+
person = Person.new
|
268
|
+
person.should respond_to(:name=)
|
269
|
+
end
|
270
|
+
|
271
|
+
context "when setting the association directly" do
|
272
|
+
|
273
|
+
before do
|
274
|
+
@attributes = { :title => "Sir",
|
275
|
+
:name => { :first_name => "Test" } }
|
276
|
+
@person = Person.new(@attributes)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "sets the attributes for the association" do
|
280
|
+
name = Name.new(:first_name => "New Name", :document_class => "Name")
|
281
|
+
@person.name = name
|
282
|
+
@person.name.first_name.should == "New Name"
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
describe "#index" do
|
290
|
+
|
291
|
+
context "when unique options are not provided" do
|
292
|
+
|
293
|
+
it "delegates to collection with unique => false" do
|
294
|
+
@collection.expects(:create_index).with(:title, :unique => false)
|
295
|
+
Person.index :title
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
context "when unique option is provided" do
|
301
|
+
|
302
|
+
it "delegates to collection with unique option" do
|
303
|
+
@collection.expects(:create_index).with(:title, :unique => true)
|
304
|
+
Person.index :title, :unique => true
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "#new" do
|
312
|
+
|
313
|
+
context "with no attributes" do
|
314
|
+
|
315
|
+
it "does not set any attributes" do
|
316
|
+
person = Person.new
|
317
|
+
person.attributes.empty?.should be_true
|
318
|
+
end
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
context "with attributes" do
|
323
|
+
|
324
|
+
before do
|
325
|
+
@attributes = { :test => "test" }
|
326
|
+
end
|
327
|
+
|
328
|
+
it "sets the arributes hash on the object" do
|
329
|
+
person = Person.new(@attributes)
|
330
|
+
person.attributes.should == @attributes
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
describe "#new_record?" do
|
338
|
+
|
339
|
+
context "when the object has been saved" do
|
340
|
+
|
341
|
+
before do
|
342
|
+
@person = Person.new(:_id => "1")
|
343
|
+
end
|
344
|
+
|
345
|
+
it "returns false" do
|
346
|
+
@person.new_record?.should be_false
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
context "when the object has not been saved" do
|
352
|
+
|
353
|
+
before do
|
354
|
+
@person = Person.new
|
355
|
+
end
|
356
|
+
|
357
|
+
it "returns true" do
|
358
|
+
@person.new_record?.should be_true
|
359
|
+
end
|
360
|
+
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
describe "#paginate" do
|
366
|
+
|
367
|
+
before do
|
368
|
+
@cursor = stub(:count => 100, :collect => [])
|
369
|
+
end
|
370
|
+
|
371
|
+
context "when pagination parameters are passed" do
|
372
|
+
|
373
|
+
it "delegates to will paginate with the results" do
|
374
|
+
@collection.expects(:find).with({ :test => "Test" }, {:limit => 20, :offset => 20}).returns(@cursor)
|
375
|
+
Person.paginate({ :conditions => { :test => "Test" } }, { :page => 2, :per_page => 20 })
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
context "when pagination parameters are not passed" do
|
381
|
+
|
382
|
+
it "delegates to will paginate with default values" do
|
383
|
+
@collection.expects(:find).with({ :test => "Test" }, {:limit => 20, :offset => 0}).returns(@cursor)
|
384
|
+
Person.paginate(:conditions => { :test => "Test" })
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
describe "#parent" do
|
392
|
+
|
393
|
+
before do
|
394
|
+
@attributes = { :title => "Sir",
|
395
|
+
:addresses => [
|
396
|
+
{ :street => "Street 1", :document_class => "Address" },
|
397
|
+
{ :street => "Street 2", :document_class => "Address" } ] }
|
398
|
+
@person = Person.new(@attributes)
|
399
|
+
end
|
400
|
+
|
401
|
+
context "when document is embedded" do
|
402
|
+
|
403
|
+
it "returns the parent document" do
|
404
|
+
@person.addresses.first.parent.should == @person
|
405
|
+
end
|
406
|
+
|
407
|
+
end
|
408
|
+
|
409
|
+
context "when document is root" do
|
410
|
+
|
411
|
+
it "returns nil" do
|
412
|
+
@person.parent.should be_nil
|
413
|
+
end
|
414
|
+
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|
418
|
+
|
419
|
+
describe "#save" do
|
420
|
+
|
421
|
+
context "when the document is the root" do
|
422
|
+
|
423
|
+
before do
|
424
|
+
@attributes = { :test => "test" }
|
425
|
+
@person = Person.new(@attributes)
|
426
|
+
end
|
427
|
+
|
428
|
+
it "persists the object to the MongoDB collection" do
|
429
|
+
@collection.expects(:save).with(@person.attributes)
|
430
|
+
@person.save.should be_true
|
431
|
+
end
|
432
|
+
|
433
|
+
end
|
434
|
+
|
435
|
+
context "when the document is embedded" do
|
436
|
+
|
437
|
+
before do
|
438
|
+
@attributes = { :title => "Sir",
|
439
|
+
:addresses => [
|
440
|
+
{ :street => "Street 1", :document_class => "Address" },
|
441
|
+
{ :street => "Street 2", :document_class => "Address" } ] }
|
442
|
+
@person = Person.new(@attributes)
|
443
|
+
end
|
444
|
+
|
445
|
+
it "saves the root document" do
|
446
|
+
@collection.expects(:save).with(@person.attributes)
|
447
|
+
@person.addresses.first.save
|
448
|
+
end
|
449
|
+
|
450
|
+
end
|
451
|
+
|
452
|
+
end
|
453
|
+
|
454
|
+
describe "#to_param" do
|
455
|
+
|
456
|
+
it "returns the id" do
|
457
|
+
id = Mongo::ObjectID.new
|
458
|
+
Person.new(:_id => id).to_param.should == id.to_s
|
459
|
+
end
|
460
|
+
|
461
|
+
end
|
462
|
+
|
463
|
+
describe "#update_attributes" do
|
464
|
+
|
465
|
+
context "when attributes are provided" do
|
466
|
+
|
467
|
+
it "saves and returns true" do
|
468
|
+
person = Person.new
|
469
|
+
person.expects(:save).returns(true)
|
470
|
+
person.update_attributes(:test => "Test").should be_true
|
471
|
+
end
|
472
|
+
|
473
|
+
end
|
474
|
+
|
475
|
+
end
|
476
|
+
|
477
|
+
context "validations" do
|
478
|
+
|
479
|
+
context "when defining using macros" do
|
480
|
+
|
481
|
+
after do
|
482
|
+
Person.validations.clear
|
483
|
+
end
|
484
|
+
|
485
|
+
describe "#validates_acceptance_of" do
|
486
|
+
|
487
|
+
it "adds the acceptance validation" do
|
488
|
+
Person.class_eval do
|
489
|
+
validates_acceptance_of :terms
|
490
|
+
end
|
491
|
+
Person.validations.first.should be_a_kind_of(Validatable::ValidatesAcceptanceOf)
|
492
|
+
end
|
493
|
+
|
494
|
+
end
|
495
|
+
|
496
|
+
describe "#validates_associated" do
|
497
|
+
|
498
|
+
it "adds the associated validation" do
|
499
|
+
Person.class_eval do
|
500
|
+
validates_associated :name
|
501
|
+
end
|
502
|
+
Person.validations.first.should be_a_kind_of(Validatable::ValidatesAssociated)
|
503
|
+
end
|
504
|
+
|
505
|
+
end
|
506
|
+
|
507
|
+
describe "#validates_format_of" do
|
508
|
+
|
509
|
+
it "adds the format validation" do
|
510
|
+
Person.class_eval do
|
511
|
+
validates_format_of :title, :with => /[A-Za-z]/
|
512
|
+
end
|
513
|
+
Person.validations.first.should be_a_kind_of(Validatable::ValidatesFormatOf)
|
514
|
+
end
|
515
|
+
|
516
|
+
end
|
517
|
+
|
518
|
+
describe "#validates_length_of" do
|
519
|
+
|
520
|
+
it "adds the length validation" do
|
521
|
+
Person.class_eval do
|
522
|
+
validates_length_of :title, :minimum => 10
|
523
|
+
end
|
524
|
+
Person.validations.first.should be_a_kind_of(Validatable::ValidatesLengthOf)
|
525
|
+
end
|
526
|
+
|
527
|
+
end
|
528
|
+
|
529
|
+
describe "#validates_numericality_of" do
|
530
|
+
|
531
|
+
it "adds the numericality validation" do
|
532
|
+
Person.class_eval do
|
533
|
+
validates_numericality_of :age
|
534
|
+
end
|
535
|
+
Person.validations.first.should be_a_kind_of(Validatable::ValidatesNumericalityOf)
|
536
|
+
end
|
537
|
+
|
538
|
+
end
|
539
|
+
|
540
|
+
describe "#validates_presence_of" do
|
541
|
+
|
542
|
+
it "adds the presence validation" do
|
543
|
+
Person.class_eval do
|
544
|
+
validates_presence_of :title
|
545
|
+
end
|
546
|
+
Person.validations.first.should be_a_kind_of(Validatable::ValidatesPresenceOf)
|
547
|
+
end
|
548
|
+
|
549
|
+
end
|
550
|
+
|
551
|
+
describe "#validates_true_for" do
|
552
|
+
|
553
|
+
it "adds the true validation" do
|
554
|
+
Person.class_eval do
|
555
|
+
validates_true_for :title, :logic => lambda { title == "Esquire" }
|
556
|
+
end
|
557
|
+
Person.validations.first.should be_a_kind_of(Validatable::ValidatesTrueFor)
|
558
|
+
end
|
559
|
+
|
560
|
+
end
|
561
|
+
|
562
|
+
end
|
563
|
+
|
564
|
+
context "when running validations" do
|
565
|
+
|
566
|
+
before do
|
567
|
+
@person = Person.new
|
568
|
+
end
|
569
|
+
|
570
|
+
after do
|
571
|
+
Person.validations.clear
|
572
|
+
end
|
573
|
+
|
574
|
+
describe "#validates_acceptance_of" do
|
575
|
+
|
576
|
+
it "fails if field not accepted" do
|
577
|
+
Person.class_eval do
|
578
|
+
validates_acceptance_of :terms
|
579
|
+
end
|
580
|
+
@person.valid?.should be_false
|
581
|
+
@person.errors.on(:terms).should_not be_nil
|
582
|
+
end
|
583
|
+
|
584
|
+
end
|
585
|
+
|
586
|
+
describe "#validates_associated" do
|
587
|
+
|
588
|
+
context "when association is a has_many" do
|
589
|
+
|
590
|
+
it "fails when any association fails validation"
|
591
|
+
|
592
|
+
end
|
593
|
+
|
594
|
+
context "when association is a has_one" do
|
595
|
+
|
596
|
+
it "fails when the association fails validation" do
|
597
|
+
Person.class_eval do
|
598
|
+
validates_associated :name
|
599
|
+
end
|
600
|
+
Name.class_eval do
|
601
|
+
validates_presence_of :first_name
|
602
|
+
end
|
603
|
+
@person.name = Name.new
|
604
|
+
@person.valid?.should be_false
|
605
|
+
@person.errors.on(:name).should_not be_nil
|
606
|
+
end
|
607
|
+
|
608
|
+
end
|
609
|
+
|
610
|
+
end
|
611
|
+
|
612
|
+
describe "#validates_format_of" do
|
613
|
+
|
614
|
+
it "fails if the field is in the wrong format" do
|
615
|
+
Person.class_eval do
|
616
|
+
validates_format_of :title, :with => /[A-Za-z]/
|
617
|
+
end
|
618
|
+
@person.title = 10
|
619
|
+
@person.valid?.should be_false
|
620
|
+
@person.errors.on(:title).should_not be_nil
|
621
|
+
end
|
622
|
+
|
623
|
+
end
|
624
|
+
|
625
|
+
describe "#validates_length_of" do
|
626
|
+
|
627
|
+
it "fails if the field is the wrong length" do
|
628
|
+
Person.class_eval do
|
629
|
+
validates_length_of :title, :minimum => 10
|
630
|
+
end
|
631
|
+
@person.title = "Testing"
|
632
|
+
@person.valid?.should be_false
|
633
|
+
@person.errors.on(:title).should_not be_nil
|
634
|
+
end
|
635
|
+
|
636
|
+
end
|
637
|
+
|
638
|
+
describe "#validates_numericality_of" do
|
639
|
+
|
640
|
+
it "fails if the field is not a number" do
|
641
|
+
Person.class_eval do
|
642
|
+
validates_numericality_of :age
|
643
|
+
end
|
644
|
+
@person.age = "foo"
|
645
|
+
@person.valid?.should be_false
|
646
|
+
@person.errors.on(:age).should_not be_nil
|
647
|
+
end
|
648
|
+
|
649
|
+
end
|
650
|
+
|
651
|
+
describe "#validates_presence_of" do
|
652
|
+
|
653
|
+
it "fails if the field is nil" do
|
654
|
+
Person.class_eval do
|
655
|
+
validates_presence_of :title
|
656
|
+
end
|
657
|
+
@person.valid?.should be_false
|
658
|
+
@person.errors.on(:title).should_not be_nil
|
659
|
+
end
|
660
|
+
|
661
|
+
end
|
662
|
+
|
663
|
+
describe "#validates_true_for" do
|
664
|
+
|
665
|
+
it "fails if the logic returns false" do
|
666
|
+
Person.class_eval do
|
667
|
+
validates_true_for :title, :logic => lambda { title == "Esquire" }
|
668
|
+
end
|
669
|
+
@person.valid?.should be_false
|
670
|
+
@person.errors.on(:title).should_not be_nil
|
671
|
+
end
|
672
|
+
|
673
|
+
end
|
674
|
+
|
675
|
+
end
|
676
|
+
|
677
|
+
end
|
678
|
+
|
679
|
+
|
680
|
+
end
|