mongo_mapper 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +7 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +39 -0
  4. data/Rakefile +87 -0
  5. data/VERSION +1 -0
  6. data/bin/mmconsole +55 -0
  7. data/lib/mongo_mapper.rb +92 -0
  8. data/lib/mongo_mapper/associations.rb +86 -0
  9. data/lib/mongo_mapper/associations/base.rb +83 -0
  10. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +34 -0
  11. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +22 -0
  12. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +27 -0
  13. data/lib/mongo_mapper/associations/many_documents_proxy.rb +116 -0
  14. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +33 -0
  15. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +67 -0
  16. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +11 -0
  17. data/lib/mongo_mapper/associations/many_proxy.rb +6 -0
  18. data/lib/mongo_mapper/associations/proxy.rb +64 -0
  19. data/lib/mongo_mapper/callbacks.rb +106 -0
  20. data/lib/mongo_mapper/document.rb +317 -0
  21. data/lib/mongo_mapper/dynamic_finder.rb +35 -0
  22. data/lib/mongo_mapper/embedded_document.rb +354 -0
  23. data/lib/mongo_mapper/finder_options.rb +94 -0
  24. data/lib/mongo_mapper/key.rb +32 -0
  25. data/lib/mongo_mapper/observing.rb +50 -0
  26. data/lib/mongo_mapper/pagination.rb +51 -0
  27. data/lib/mongo_mapper/rails_compatibility/document.rb +15 -0
  28. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +27 -0
  29. data/lib/mongo_mapper/save_with_validation.rb +19 -0
  30. data/lib/mongo_mapper/serialization.rb +55 -0
  31. data/lib/mongo_mapper/serializers/json_serializer.rb +92 -0
  32. data/lib/mongo_mapper/support.rb +157 -0
  33. data/lib/mongo_mapper/validations.rb +69 -0
  34. data/mongo_mapper.gemspec +156 -0
  35. data/test/NOTE_ON_TESTING +1 -0
  36. data/test/custom_matchers.rb +48 -0
  37. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +54 -0
  38. data/test/functional/associations/test_belongs_to_proxy.rb +46 -0
  39. data/test/functional/associations/test_many_documents_as_proxy.rb +244 -0
  40. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +132 -0
  41. data/test/functional/associations/test_many_embedded_proxy.rb +174 -0
  42. data/test/functional/associations/test_many_polymorphic_proxy.rb +297 -0
  43. data/test/functional/associations/test_many_proxy.rb +331 -0
  44. data/test/functional/test_associations.rb +48 -0
  45. data/test/functional/test_binary.rb +18 -0
  46. data/test/functional/test_callbacks.rb +85 -0
  47. data/test/functional/test_document.rb +951 -0
  48. data/test/functional/test_embedded_document.rb +97 -0
  49. data/test/functional/test_pagination.rb +87 -0
  50. data/test/functional/test_rails_compatibility.rb +30 -0
  51. data/test/functional/test_validations.rb +279 -0
  52. data/test/models.rb +169 -0
  53. data/test/test_helper.rb +29 -0
  54. data/test/unit/serializers/test_json_serializer.rb +189 -0
  55. data/test/unit/test_association_base.rb +144 -0
  56. data/test/unit/test_document.rb +165 -0
  57. data/test/unit/test_dynamic_finder.rb +125 -0
  58. data/test/unit/test_embedded_document.rb +645 -0
  59. data/test/unit/test_finder_options.rb +193 -0
  60. data/test/unit/test_key.rb +163 -0
  61. data/test/unit/test_mongomapper.rb +28 -0
  62. data/test/unit/test_observing.rb +101 -0
  63. data/test/unit/test_pagination.rb +109 -0
  64. data/test/unit/test_rails_compatibility.rb +39 -0
  65. data/test/unit/test_serializations.rb +52 -0
  66. data/test/unit/test_support.rb +272 -0
  67. data/test/unit/test_time_zones.rb +40 -0
  68. data/test/unit/test_validations.rb +503 -0
  69. metadata +204 -0
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ class TimeZonesTest < Test::Unit::TestCase
4
+ context "An instance of an embedded document" do
5
+ setup do
6
+ @document = Class.new do
7
+ include MongoMapper::EmbeddedDocument
8
+ key :name, String
9
+ key :created_at, Time
10
+ end
11
+ end
12
+
13
+ should "work without Time.zone" do
14
+ Time.zone = nil
15
+
16
+ doc = @document.new(:created_at => "2009-08-15 14:00:00")
17
+ doc.created_at.should == Time.local(2009, 8, 15, 14, 0, 0).utc
18
+ end
19
+
20
+ should "work with Time.zone set to the (default) UTC" do
21
+ Time.zone = 'UTC'
22
+
23
+ doc = @document.new(:created_at => "2009-08-15 14:00:00")
24
+ doc.created_at.is_a?(ActiveSupport::TimeWithZone).should be_true
25
+ doc.created_at.should == Time.utc(2009, 8, 15, 14)
26
+
27
+ Time.zone = nil
28
+ end
29
+
30
+ should_eventually "work with timezones that are not UTC" do
31
+ Time.zone = 'Hawaii'
32
+
33
+ doc = @document.new(:created_at => @original_time)
34
+ doc.created_at.is_a?(ActiveSupport::TimeWithZone).should be_true
35
+ doc.created_at.should == Time.utc(2009, 8, 16)
36
+
37
+ Time.zone = nil
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,503 @@
1
+ require 'test_helper'
2
+
3
+ class ValidationsTest < Test::Unit::TestCase
4
+ context "Validations" do
5
+
6
+ context "on a Document" do
7
+
8
+ setup do
9
+ @document = Class.new do
10
+ include MongoMapper::Document
11
+ set_collection_name 'test'
12
+ end
13
+ end
14
+
15
+ context "Validating acceptance of" do
16
+ should "work with validates_acceptance_of macro" do
17
+ @document.key :terms, String
18
+ @document.validates_acceptance_of :terms
19
+ doc = @document.new(:terms => '')
20
+ doc.should have_error_on(:terms)
21
+ doc.terms = '1'
22
+ doc.should_not have_error_on(:terms)
23
+ end
24
+ end
25
+
26
+ context "validating confirmation of" do
27
+ should "work with validates_confirmation_of macro" do
28
+ @document.key :password, String
29
+ @document.validates_confirmation_of :password
30
+ doc = @document.new
31
+ doc.password = 'foobar'
32
+ doc.should have_error_on(:password)
33
+ doc.password_confirmation = 'foobar'
34
+ doc.should_not have_error_on(:password)
35
+ end
36
+ end
37
+
38
+ context "validating format of" do
39
+ should "work with validates_format_of macro" do
40
+ @document.key :name, String
41
+ @document.validates_format_of :name, :with => /.+/
42
+ doc = @document.new
43
+ doc.should have_error_on(:name)
44
+ doc.name = 'John'
45
+ doc.should_not have_error_on(:name)
46
+ end
47
+
48
+ should "work with :format shorcut key" do
49
+ @document.key :name, String, :format => /.+/
50
+ doc = @document.new
51
+ doc.should have_error_on(:name)
52
+ doc.name = 'John'
53
+ doc.should_not have_error_on(:name)
54
+ end
55
+ end
56
+
57
+ context "validating length of" do
58
+ should "work with validates_length_of macro" do
59
+ @document.key :name, String
60
+ @document.validates_length_of :name, :minimum => 5
61
+ doc = @document.new
62
+ doc.should have_error_on(:name)
63
+ end
64
+
65
+ context "with :length => integer shortcut" do
66
+ should "set maximum of integer provided" do
67
+ @document.key :name, String, :length => 5
68
+ doc = @document.new
69
+ doc.name = '123456'
70
+ doc.should have_error_on(:name)
71
+ doc.name = '12345'
72
+ doc.should_not have_error_on(:name)
73
+ end
74
+ end
75
+
76
+ context "with :length => range shortcut" do
77
+ setup do
78
+ @document.key :name, String, :length => 5..7
79
+ end
80
+
81
+ should "set minimum of range min" do
82
+ doc = @document.new
83
+ doc.should have_error_on(:name)
84
+ doc.name = '123456'
85
+ doc.should_not have_error_on(:name)
86
+ end
87
+
88
+ should "set maximum of range max" do
89
+ doc = @document.new
90
+ doc.should have_error_on(:name)
91
+ doc.name = '12345678'
92
+ doc.should have_error_on(:name)
93
+ doc.name = '123456'
94
+ doc.should_not have_error_on(:name)
95
+ end
96
+ end
97
+
98
+ context "with :length => hash shortcut" do
99
+ should "pass options through" do
100
+ @document.key :name, String, :length => {:minimum => 2}
101
+ doc = @document.new
102
+ doc.should have_error_on(:name)
103
+ doc.name = '12'
104
+ doc.should_not have_error_on(:name)
105
+ end
106
+ end
107
+ end # validates_length_of
108
+
109
+ context "Validating numericality of" do
110
+ should "work with validates_numericality_of macro" do
111
+ @document.key :age, Integer
112
+ @document.validates_numericality_of :age
113
+ doc = @document.new
114
+ doc.age = 'String'
115
+ doc.should have_error_on(:age)
116
+ doc.age = 23
117
+ doc.should_not have_error_on(:age)
118
+ end
119
+
120
+ context "with :numeric shortcut" do
121
+ should "work with integer or float" do
122
+ @document.key :weight, Float, :numeric => true
123
+ doc = @document.new
124
+ doc.weight = 'String'
125
+ doc.should have_error_on(:weight)
126
+ doc.weight = 23.0
127
+ doc.should_not have_error_on(:weight)
128
+ doc.weight = 23
129
+ doc.should_not have_error_on(:weight)
130
+ end
131
+ end
132
+
133
+ context "with :numeric shortcut on Integer key" do
134
+ should "only work with integers" do
135
+ @document.key :age, Integer, :numeric => true
136
+ doc = @document.new
137
+ doc.age = 'String'
138
+ doc.should have_error_on(:age)
139
+ doc.age = 23.1
140
+ doc.should have_error_on(:age)
141
+ doc.age = 23
142
+ doc.should_not have_error_on(:age)
143
+ end
144
+ end
145
+ end # numericality of
146
+
147
+ context "validating presence of" do
148
+ should "work with validates_presence_of macro" do
149
+ @document.key :name, String
150
+ @document.validates_presence_of :name
151
+ doc = @document.new
152
+ doc.should have_error_on(:name)
153
+ end
154
+
155
+ should "work with :required shortcut on key definition" do
156
+ @document.key :name, String, :required => true
157
+ doc = @document.new
158
+ doc.should have_error_on(:name)
159
+ end
160
+ end
161
+
162
+ context "validating exclusion of" do
163
+ should "throw error if enumerator not provided" do
164
+ @document.key :action, String
165
+ lambda {
166
+ @document.validates_exclusion_of :action
167
+ }.should raise_error(ArgumentError)
168
+ end
169
+
170
+ should "work with validates_exclusion_of macro" do
171
+ @document.key :action, String
172
+ @document.validates_exclusion_of :action, :within => %w(kick run)
173
+
174
+ doc = @document.new
175
+ doc.should_not have_error_on(:action)
176
+
177
+ doc.action = 'fart'
178
+ doc.should_not have_error_on(:action)
179
+
180
+ doc.action = 'kick'
181
+ doc.should have_error_on(:action, 'is reserved')
182
+ end
183
+
184
+ should "not have error if allow nil is true and value is nil" do
185
+ @document.key :action, String
186
+ @document.validates_exclusion_of :action, :within => %w(kick run), :allow_nil => true
187
+
188
+ doc = @document.new
189
+ doc.should_not have_error_on(:action)
190
+ end
191
+
192
+ should "not have error if allow blank is true and value is blank" do
193
+ @document.key :action, String
194
+ @document.validates_exclusion_of :action, :within => %w(kick run), :allow_nil => true
195
+
196
+ doc = @document.new(:action => '')
197
+ doc.should_not have_error_on(:action)
198
+ end
199
+ end
200
+
201
+ context "validating inclusion of" do
202
+ should "throw error if enumerator not provided" do
203
+ @document.key :action, String
204
+ lambda {
205
+ @document.validates_inclusion_of :action
206
+ }.should raise_error(ArgumentError)
207
+ end
208
+
209
+ should "work with validates_inclusion_of macro" do
210
+ @document.key :action, String
211
+ @document.validates_inclusion_of :action, :within => %w(kick run)
212
+
213
+ doc = @document.new
214
+ doc.should have_error_on(:action, 'is not in the list')
215
+
216
+ doc.action = 'fart'
217
+ doc.should have_error_on(:action, 'is not in the list')
218
+
219
+ doc.action = 'kick'
220
+ doc.should_not have_error_on(:action)
221
+ end
222
+
223
+ should "not have error if allow nil is true and value is nil" do
224
+ @document.key :action, String
225
+ @document.validates_inclusion_of :action, :within => %w(kick run), :allow_nil => true
226
+
227
+ doc = @document.new
228
+ doc.should_not have_error_on(:action)
229
+ end
230
+
231
+ should "not have error if allow blank is true and value is blank" do
232
+ @document.key :action, String
233
+ @document.validates_inclusion_of :action, :within => %w(kick run), :allow_blank => true
234
+
235
+ doc = @document.new(:action => '')
236
+ doc.should_not have_error_on(:action)
237
+ end
238
+ end
239
+
240
+ end # End on a Document
241
+
242
+ context "On an EmbeddedDocument" do
243
+
244
+ setup do
245
+ @embedded_doc = Class.new do
246
+ include MongoMapper::EmbeddedDocument
247
+ end
248
+ end
249
+
250
+ context "Validating acceptance of" do
251
+ should "work with validates_acceptance_of macro" do
252
+ @embedded_doc.key :terms, String
253
+ @embedded_doc.validates_acceptance_of :terms
254
+ doc = @embedded_doc.new(:terms => '')
255
+ doc.should have_error_on(:terms)
256
+ doc.terms = '1'
257
+ doc.should_not have_error_on(:terms)
258
+ end
259
+ end
260
+
261
+ context "validating confirmation of" do
262
+ should "work with validates_confirmation_of macro" do
263
+ @embedded_doc.key :password, String
264
+ @embedded_doc.validates_confirmation_of :password
265
+ doc = @embedded_doc.new
266
+ doc.password = 'foobar'
267
+ doc.should have_error_on(:password)
268
+ doc.password_confirmation = 'foobar'
269
+ doc.should_not have_error_on(:password)
270
+ end
271
+ end
272
+
273
+ context "validating format of" do
274
+ should "work with validates_format_of macro" do
275
+ @embedded_doc.key :name, String
276
+ @embedded_doc.validates_format_of :name, :with => /.+/
277
+ doc = @embedded_doc.new
278
+ doc.should have_error_on(:name)
279
+ doc.name = 'John'
280
+ doc.should_not have_error_on(:name)
281
+ end
282
+
283
+ should "work with :format shorcut key" do
284
+ @embedded_doc.key :name, String, :format => /.+/
285
+ doc = @embedded_doc.new
286
+ doc.should have_error_on(:name)
287
+ doc.name = 'John'
288
+ doc.should_not have_error_on(:name)
289
+ end
290
+ end
291
+
292
+ context "validating length of" do
293
+ should "work with validates_length_of macro" do
294
+ @embedded_doc.key :name, String
295
+ @embedded_doc.validates_length_of :name, :minimum => 5
296
+ doc = @embedded_doc.new
297
+ doc.should have_error_on(:name)
298
+ end
299
+
300
+ context "with :length => integer shortcut" do
301
+ should "set maximum of integer provided" do
302
+ @embedded_doc.key :name, String, :length => 5
303
+ doc = @embedded_doc.new
304
+ doc.name = '123456'
305
+ doc.should have_error_on(:name)
306
+ doc.name = '12345'
307
+ doc.should_not have_error_on(:name)
308
+ end
309
+ end
310
+
311
+ context "with :length => range shortcut" do
312
+ setup do
313
+ @embedded_doc.key :name, String, :length => 5..7
314
+ end
315
+
316
+ should "set minimum of range min" do
317
+ doc = @embedded_doc.new
318
+ doc.should have_error_on(:name)
319
+ doc.name = '123456'
320
+ doc.should_not have_error_on(:name)
321
+ end
322
+
323
+ should "set maximum of range max" do
324
+ doc = @embedded_doc.new
325
+ doc.should have_error_on(:name)
326
+ doc.name = '12345678'
327
+ doc.should have_error_on(:name)
328
+ doc.name = '123456'
329
+ doc.should_not have_error_on(:name)
330
+ end
331
+ end
332
+
333
+ context "with :length => hash shortcut" do
334
+ should "pass options through" do
335
+ @embedded_doc.key :name, String, :length => {:minimum => 2}
336
+ doc = @embedded_doc.new
337
+ doc.should have_error_on(:name)
338
+ doc.name = '12'
339
+ doc.should_not have_error_on(:name)
340
+ end
341
+ end
342
+ end # validates_length_of
343
+
344
+ context "Validating numericality of" do
345
+ should "work with validates_numericality_of macro" do
346
+ @embedded_doc.key :age, Integer
347
+ @embedded_doc.validates_numericality_of :age
348
+ doc = @embedded_doc.new
349
+ doc.age = 'String'
350
+ doc.should have_error_on(:age)
351
+ doc.age = 23
352
+ doc.should_not have_error_on(:age)
353
+ end
354
+
355
+ context "with :numeric shortcut" do
356
+ should "work with integer or float" do
357
+ @embedded_doc.key :weight, Float, :numeric => true
358
+ doc = @embedded_doc.new
359
+ doc.weight = 'String'
360
+ doc.should have_error_on(:weight)
361
+ doc.weight = 23.0
362
+ doc.should_not have_error_on(:weight)
363
+ doc.weight = 23
364
+ doc.should_not have_error_on(:weight)
365
+ end
366
+ end
367
+
368
+ context "with :numeric shortcut on Integer key" do
369
+ should "only work with integers" do
370
+ @embedded_doc.key :age, Integer, :numeric => true
371
+ doc = @embedded_doc.new
372
+ doc.age = 'String'
373
+ doc.should have_error_on(:age)
374
+ doc.age = 23.1
375
+ doc.should have_error_on(:age)
376
+ doc.age = 23
377
+ doc.should_not have_error_on(:age)
378
+ end
379
+ end
380
+ end # numericality of
381
+
382
+ context "validating presence of" do
383
+ should "work with validates_presence_of macro" do
384
+ @embedded_doc.key :name, String
385
+ @embedded_doc.validates_presence_of :name
386
+ doc = @embedded_doc.new
387
+ doc.should have_error_on(:name)
388
+ end
389
+
390
+ should "work with :required shortcut on key definition" do
391
+ @embedded_doc.key :name, String, :required => true
392
+ doc = @embedded_doc.new
393
+ doc.should have_error_on(:name)
394
+ end
395
+ end
396
+
397
+ context "validating exclusion of" do
398
+ should "throw error if enumerator not provided" do
399
+ @embedded_doc.key :action, String
400
+ lambda {
401
+ @embedded_doc.validates_exclusion_of :action
402
+ }.should raise_error(ArgumentError)
403
+ end
404
+
405
+ should "work with validates_exclusion_of macro" do
406
+ @embedded_doc.key :action, String
407
+ @embedded_doc.validates_exclusion_of :action, :within => %w(kick run)
408
+
409
+ doc = @embedded_doc.new
410
+ doc.should_not have_error_on(:action)
411
+
412
+ doc.action = 'fart'
413
+ doc.should_not have_error_on(:action)
414
+
415
+ doc.action = 'kick'
416
+ doc.should have_error_on(:action, 'is reserved')
417
+ end
418
+
419
+ should "not have error if allow nil is true and value is nil" do
420
+ @embedded_doc.key :action, String
421
+ @embedded_doc.validates_exclusion_of :action, :within => %w(kick run), :allow_nil => true
422
+
423
+ doc = @embedded_doc.new
424
+ doc.should_not have_error_on(:action)
425
+ end
426
+
427
+ should "not have error if allow blank is true and value is blank" do
428
+ @embedded_doc.key :action, String
429
+ @embedded_doc.validates_exclusion_of :action, :within => %w(kick run), :allow_nil => true
430
+
431
+ doc = @embedded_doc.new(:action => '')
432
+ doc.should_not have_error_on(:action)
433
+ end
434
+ end
435
+
436
+ context "validating inclusion of" do
437
+ should "throw error if enumerator not provided" do
438
+ @embedded_doc.key :action, String
439
+ lambda {
440
+ @embedded_doc.validates_inclusion_of :action
441
+ }.should raise_error(ArgumentError)
442
+ end
443
+
444
+ should "work with validates_inclusion_of macro" do
445
+ @embedded_doc.key :action, String
446
+ @embedded_doc.validates_inclusion_of :action, :within => %w(kick run)
447
+
448
+ doc = @embedded_doc.new
449
+ doc.should have_error_on(:action, 'is not in the list')
450
+
451
+ doc.action = 'fart'
452
+ doc.should have_error_on(:action, 'is not in the list')
453
+
454
+ doc.action = 'kick'
455
+ doc.should_not have_error_on(:action)
456
+ end
457
+
458
+ should "not have error if allow nil is true and value is nil" do
459
+ @embedded_doc.key :action, String
460
+ @embedded_doc.validates_inclusion_of :action, :within => %w(kick run), :allow_nil => true
461
+
462
+ doc = @embedded_doc.new
463
+ doc.should_not have_error_on(:action)
464
+ end
465
+
466
+ should "not have error if allow blank is true and value is blank" do
467
+ @embedded_doc.key :action, String
468
+ @embedded_doc.validates_inclusion_of :action, :within => %w(kick run), :allow_blank => true
469
+
470
+ doc = @embedded_doc.new(:action => '')
471
+ doc.should_not have_error_on(:action)
472
+ end
473
+ end
474
+
475
+ end # End on an EmbeddedDocument
476
+
477
+ end # Validations
478
+
479
+ context "Adding validation errors" do
480
+ setup do
481
+ @document = Class.new do
482
+ include MongoMapper::Document
483
+ set_collection_name 'test'
484
+
485
+ key :action, String
486
+ def action_present
487
+ errors.add(:action, 'is invalid') if action.blank?
488
+ end
489
+ end
490
+ end
491
+
492
+ should "work with validate callback" do
493
+ @document.validate :action_present
494
+
495
+ doc = @document.new
496
+ doc.action = nil
497
+ doc.should have_error_on(:action)
498
+
499
+ doc.action = 'kick'
500
+ doc.should_not have_error_on(:action)
501
+ end
502
+ end
503
+ end