mongo_record 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,774 @@
1
+ # Copyright 2009 10gen, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '../lib')
16
+ require 'rubygems'
17
+ require 'test/unit'
18
+ require 'mongo_record'
19
+ require File.join(File.dirname(__FILE__), 'course')
20
+ require File.join(File.dirname(__FILE__), 'address')
21
+ require File.join(File.dirname(__FILE__), 'student')
22
+ require File.join(File.dirname(__FILE__), 'class_in_module')
23
+
24
+ class Track < MongoRecord::Base
25
+ collection_name :tracks
26
+ fields :artist, :album, :song, :track, :created_at
27
+
28
+ def to_s
29
+ # Uses both accessor methods and ivars themselves
30
+ "artist: #{artist}, album: #{album}, song: #@song, track: #{@track ? @track.to_i : nil}"
31
+ end
32
+ end
33
+
34
+ # Same class, but this time class.name.downcase == collection name so we don't
35
+ # have to call collection_name.
36
+ class Rubytest < MongoRecord::Base
37
+ fields :artist, :album, :song, :track
38
+ def to_s
39
+ "artist: #{artist}, album: #{album}, song: #{song}, track: #{track ? track.to_i : nil}"
40
+ end
41
+ end
42
+
43
+ # Class without any fields defined to test inserting custom attributes
44
+ class Playlist < MongoRecord::Base
45
+ collection_name :playlists
46
+ end
47
+
48
+ class MongoTest < Test::Unit::TestCase
49
+
50
+ @@host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
51
+ @@port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::Connection::DEFAULT_PORT
52
+ @@db = Mongo::Connection.new(@@host, @@port).db('mongorecord-test')
53
+ @@students = @@db.collection('students')
54
+ @@courses = @@db.collection('courses')
55
+ @@tracks = @@db.collection('tracks')
56
+ @@playlists = @@db.collection('playlists')
57
+
58
+ def setup
59
+ super
60
+ MongoRecord::Base.connection = @@db
61
+
62
+ @@students.clear
63
+ @@courses.clear
64
+ @@tracks.clear
65
+ @@playlists.clear
66
+
67
+ # Manually insert data without using MongoRecord::Base
68
+ @@tracks.insert({:_id => Mongo::ObjectID.new, :artist => 'Thomas Dolby', :album => 'Aliens Ate My Buick', :song => 'The Ability to Swing'})
69
+ @@tracks.insert({:_id => Mongo::ObjectID.new, :artist => 'Thomas Dolby', :album => 'Aliens Ate My Buick', :song => 'Budapest by Blimp'})
70
+ @@tracks.insert({:_id => Mongo::ObjectID.new, :artist => 'Thomas Dolby', :album => 'The Golden Age of Wireless', :song => 'Europa and the Pirate Twins'})
71
+ @@tracks.insert({:_id => Mongo::ObjectID.new, :artist => 'XTC', :album => 'Oranges & Lemons', :song => 'Garden Of Earthly Delights', :track => 1})
72
+ @mayor_id = Mongo::ObjectID.new
73
+ @@tracks.insert({:_id => @mayor_id, :artist => 'XTC', :album => 'Oranges & Lemons', :song => 'The Mayor Of Simpleton', :track => 2})
74
+ @@tracks.insert({:_id => Mongo::ObjectID.new, :artist => 'XTC', :album => 'Oranges & Lemons', :song => 'King For A Day', :track => 3})
75
+
76
+ @mayor_str = "artist: XTC, album: Oranges & Lemons, song: The Mayor Of Simpleton, track: 2"
77
+ @mayor_song = 'The Mayor Of Simpleton'
78
+
79
+ @spongebob_addr = Address.new(:street => "3 Pineapple Lane", :city => "Bikini Bottom", :state => "HI", :postal_code => "12345")
80
+ @bender_addr = Address.new(:street => "Planet Express", :city => "New New York", :state => "NY", :postal_code => "10001")
81
+ @course1 = Course.new(:name => 'Introductory Testing')
82
+ @course2 = Course.new(:name => 'Advanced Phlogiston Combuston Theory')
83
+ @score1 = Score.new(:for_course => @course1, :grade => 4.0)
84
+ @score2 = Score.new(:for_course => @course2, :grade => 3.5)
85
+ end
86
+
87
+ def teardown
88
+ @@students.clear
89
+ @@courses.clear
90
+ @@tracks.clear
91
+ @@playlists.clear
92
+ super
93
+ end
94
+
95
+ def test_ivars_created
96
+ t = Track.new
97
+ %w(_id artist album song track).each { |iv|
98
+ assert t.instance_variable_defined?("@#{iv}")
99
+ }
100
+ end
101
+
102
+ def test_method_generation
103
+ x = Track.new({:artist => 1, :album => 2})
104
+
105
+ assert x.respond_to?(:_id)
106
+ assert x.respond_to?(:artist)
107
+ assert x.respond_to?(:album)
108
+ assert x.respond_to?(:song)
109
+ assert x.respond_to?(:track)
110
+ assert x.respond_to?(:_id=)
111
+ assert x.respond_to?(:artist=)
112
+ assert x.respond_to?(:album=)
113
+ assert x.respond_to?(:song=)
114
+ assert x.respond_to?(:track=)
115
+ assert x.respond_to?(:_id?)
116
+ assert x.respond_to?(:artist?)
117
+ assert x.respond_to?(:album?)
118
+ assert x.respond_to?(:song?)
119
+ assert x.respond_to?(:track?)
120
+
121
+ assert_equal(1, x.artist)
122
+ assert_equal(2, x.album)
123
+ assert_nil(x.song)
124
+ assert_nil(x.track)
125
+ end
126
+
127
+ def test_initialize_block
128
+ track = Track.new { |t|
129
+ t.artist = "Me'Shell Ndegeocello"
130
+ t.album = "Peace Beyond Passion"
131
+ t.song = "Bittersweet"
132
+ }
133
+ assert_equal "Me'Shell Ndegeocello", track.artist
134
+ assert_equal "Peace Beyond Passion", track.album
135
+ assert_equal "Bittersweet", track.song
136
+ assert !track.track?
137
+ end
138
+
139
+ def test_find_by_id
140
+ assert_equal(@mayor_str, Track.find_by_id(@mayor_id).to_s)
141
+ end
142
+
143
+ def test_find_by_custom_id
144
+ @@tracks.insert({:_id => 25, :artist => 'Mike D', :album => 'Awesome Blossom', :song => 'Hello World', :track => 5})
145
+ assert_equal("artist: Mike D, album: Awesome Blossom, song: Hello World, track: 5",
146
+ Track.find_by_id(25).to_s)
147
+
148
+ end
149
+
150
+ def test_find_by_song
151
+ assert_equal("artist: Thomas Dolby, album: Aliens Ate My Buick, song: Budapest by Blimp, track: ", Track.find_by_song('Budapest by Blimp').to_s)
152
+ end
153
+
154
+ def test_update
155
+ count = @@tracks.count()
156
+ t = Track.find_by_track(2)
157
+ t.track = 99
158
+ t.save
159
+ str = @mayor_str.sub(/2/, '99')
160
+ assert_equal(str, t.to_s)
161
+ assert_equal(str, Track.find_by_track(99).to_s)
162
+ assert_equal(count, @@tracks.count())
163
+ end
164
+
165
+ def test_find_all
166
+ assert_all_songs Track.find(:all).inject('') { |str, t| str + t.to_s }
167
+ end
168
+
169
+ def test_find_using_hash
170
+ str = Track.find(:all, :conditions => {:album => 'Aliens Ate My Buick'}).inject('') { |str, t| str + t.to_s }
171
+ assert_match(/song: The Ability to Swing/, str)
172
+ assert_match(/song: Budapest by Blimp/, str)
173
+ end
174
+
175
+ def test_find_first
176
+ t = Track.find(:first)
177
+ assert t.kind_of?(Track)
178
+ str = t.to_s
179
+ assert_match(/artist: [^,]+,/, str, "did not find non-empty artist name")
180
+ end
181
+
182
+ def test_find_first_with_search
183
+ t = Track.find(:first, :conditions => {:track => 3})
184
+ assert_not_nil t, "oops: nil track returned"
185
+ assert_equal "artist: XTC, album: Oranges & Lemons, song: King For A Day, track: 3", t.to_s
186
+ end
187
+
188
+ def test_find_first_returns_nil_if_not_found
189
+ assert_nil Track.find(:first, :conditions => {:track => 666})
190
+ end
191
+
192
+ def test_find_all_by
193
+ str = Track.find_all_by_album('Oranges & Lemons').inject('') { |str, t| str + t.to_s }
194
+ assert_match(/song: Garden Of Earthly Delights/, str)
195
+ assert_match(/song: The Mayor Of Simpleton/, str)
196
+ assert_match(/song: King For A Day/, str)
197
+ end
198
+
199
+ def test_find_using_hash_with_array_and_range
200
+ sorted_track_titles = ['Garden Of Earthly Delights', 'King For A Day', @mayor_song]
201
+
202
+ # Array
203
+ list = Track.find(:all, :conditions => {:track => [1,2,3]}).to_a
204
+ assert_equal 3, list.length
205
+ assert_equal sorted_track_titles, list.collect{|t| t.song}.sort
206
+
207
+ # Range
208
+ list = Track.find(:all, :conditions => {:track => 1..3}).to_a
209
+ assert_equal 3, list.length
210
+ assert_equal sorted_track_titles, list.collect{|t| t.song}.sort
211
+ end
212
+
213
+ def test_new_no_arg
214
+ assert_equal "artist: , album: , song: , track: ", Track.new.to_s
215
+ end
216
+
217
+ def test_new_by_hash
218
+ assert_equal("artist: Level 42, album: Standing In The Light, song: Micro-Kid, track: 1",
219
+ Track.new(:song => 'Micro-Kid', :album => 'Standing In The Light', :artist => 'Level 42', :track => 1).to_s)
220
+ end
221
+
222
+ def test_new_and_save
223
+ x = Track.new(:artist => 'Level 42', :album => 'Standing In The Light', :song => 'Micro-Kid', :track => 1)
224
+ assert_nil(x.id)
225
+ assert x.save, "x.save returned false; expected true"
226
+ x = Track.last
227
+ assert_not_nil(x.id)
228
+ z = Track.find(x.id)
229
+ assert_equal(x.to_s, z.to_s)
230
+ assert_equal(x.id, z.id)
231
+ end
232
+
233
+ def test_find_or_create_but_already_exists
234
+ assert_equal("artist: Thomas Dolby, album: Aliens Ate My Buick, song: The Ability to Swing, track: ",
235
+ Track.find_or_create_by_song('The Ability to Swing', :artist => 'ignored because song found').to_s)
236
+ end
237
+
238
+ def test_find_or_create_new_created
239
+ assert_equal("artist: New Artist, album: New Album, song: New Song, track: ",
240
+ Track.find_or_create_by_song('New Song', :artist => 'New Artist', :album => 'New Album').to_s)
241
+ end
242
+
243
+ def test_cursor_methods
244
+ assert_equal 2, Track.find(:all, :limit => 2).to_a.length
245
+ end
246
+
247
+ def test_return_nil_if_no_match
248
+ assert_nil Track.find(:first, :conditions => {:song => 'Does Not Compute'})
249
+ end
250
+
251
+ def test_raise_error_if_bogus_id
252
+ Track.find("bogus_id")
253
+ fail 'expected "find Track with ID=bogus_id" exception'
254
+ rescue => ex
255
+ assert_match /find Track with ID=bogus_id/, ex.to_s
256
+ end
257
+
258
+ def test_raise_error_if_first_and_bogus_id_in_hash
259
+ Track.find(:first, :conditions => {:_id => "bogus_id"})
260
+ fail 'expected "find Track with ID=bogus_id" exception'
261
+ rescue => ex
262
+ assert_match /find Track with ID=bogus_id/, ex.to_s
263
+ end
264
+
265
+ def test_find_options
266
+ assert_equal 2, Track.find(:all, :limit => 2).to_a.length
267
+ end
268
+
269
+ def test_order_options
270
+ tracks = Track.find(:all, :order => "song asc")
271
+ assert_not_nil tracks
272
+ assert_equal "Budapest by Blimp:Europa and the Pirate Twins:Garden Of Earthly Delights:King For A Day:The Ability to Swing:The Mayor Of Simpleton",
273
+ tracks.collect {|t| t.song }.join(':')
274
+
275
+ tracks = Track.find(:all, :order => "artist desc, song")
276
+ assert_not_nil tracks
277
+ assert_equal "Garden Of Earthly Delights:King For A Day:The Mayor Of Simpleton:Budapest by Blimp:Europa and the Pirate Twins:The Ability to Swing", tracks.collect {|t| t.song }.join(':')
278
+ end
279
+
280
+ def test_delete
281
+ Track.find(:first, :conditions => {:song => 'King For A Day'}).delete
282
+ str = Track.find(:all).inject('') { |str, t| str + t.to_s }
283
+ assert_match(/song: The Ability to Swing/, str)
284
+ assert_match(/song: Budapest by Blimp/, str)
285
+ assert_match(/song: Europa and the Pirate Twins/, str)
286
+ assert_match(/song: Garden Of Earthly Delights/, str)
287
+ assert_match(/song: The Mayor Of Simpleton/, str)
288
+ assert_no_match(/song: King For A Day/, str)
289
+ end
290
+
291
+ def test_class_delete
292
+ Track.delete(@mayor_id)
293
+ assert_no_match(/song: The Mayor Of Simpleton/, Track.find(:all).inject('') { |str, t| str + t.to_s })
294
+ end
295
+
296
+ def test_delete_all
297
+ Track.delete_all({:artist => 'XTC'})
298
+ assert_no_match(/artist: XTC/, Track.find(:all).inject('') { |str, t| str + t.to_s })
299
+
300
+ Track.delete_all(["song = ?", 'The Mayor Of Simpleton'])
301
+ assert_no_match(/song: The Mayor Of Simpleton/, Track.find(:all).inject('') { |str, t| str + t.to_s })
302
+
303
+ Track.delete_all("song = 'King For A Day'")
304
+ assert_no_match(/song: King For A Day/, Track.find(:all).inject('') { |str, t| str + t.to_s })
305
+
306
+ Track.delete_all()
307
+ assert_equal 0, Track.count
308
+ end
309
+
310
+ def test_find_by_mql_not_implemented
311
+ Track.find_by_mql("")
312
+ fail "should have raised a 'not implemented' exception"
313
+ rescue => ex
314
+ assert_equal("not implemented", ex.to_s)
315
+ end
316
+
317
+ def test_count
318
+ assert_equal 6, Track.count
319
+ assert_equal 3, Track.count(:conditions => {:artist => 'XTC'})
320
+ end
321
+
322
+ def test_count_collection_missing
323
+ @@db.drop_collection('tracks')
324
+ assert_equal 0, Track.count
325
+ end
326
+
327
+ def test_select
328
+ str = Track.find(:all, :select => :album).inject('') { |str, t| str + t.to_s }
329
+ assert str.include?("artist: , album: Oranges & Lemons, song: , track:")
330
+ end
331
+
332
+ def test_find_using_id
333
+ t = Track.find_by_song('King For A Day')
334
+ tid = t._id
335
+ # first is string id, second is ObjectID
336
+ str = Track.find([@mayor_id, tid]).inject('') { |str, t| str + t.to_s }
337
+ assert str.include?(@mayor_str)
338
+ assert str.include?('King For A Day')
339
+ end
340
+
341
+ def test_find_one_using_id
342
+ t = Track.find(@mayor_id)
343
+ assert_not_nil t
344
+ assert_match /song: The Mayor Of Simpleton/, t.to_s
345
+ end
346
+
347
+ def test_select_find_by_id
348
+ t = Track.find(@mayor_id, :select => :album)
349
+ assert t.album?
350
+ assert !t.artist?
351
+ assert !t.song?
352
+ assert !t.track?
353
+ assert_equal "artist: , album: Oranges & Lemons, song: , track: ", t.to_s
354
+ end
355
+
356
+ def test_has_one_initialize
357
+ s = Student.new(:name => 'Spongebob Squarepants', :email => 'spongebob@example.com', :address => @spongebob_addr)
358
+
359
+ assert_not_nil s.address, "Address not set correctly in Student#initialize"
360
+ assert_equal '3 Pineapple Lane', s.address.street
361
+ end
362
+
363
+ def test_has_one_save_and_find
364
+ s = Student.new(:name => 'Spongebob Squarepants', :email => 'spongebob@example.com', :address => @spongebob_addr)
365
+ s.save
366
+
367
+ s2 = Student.find(:first)
368
+ assert_equal 'Spongebob Squarepants', s2.name
369
+ assert_equal 'spongebob@example.com', s2.email
370
+ a2 = s2.address
371
+ assert_not_nil a2
372
+ assert_kind_of Address, a2
373
+ assert_equal @spongebob_addr.street, a2.street
374
+ assert_equal @spongebob_addr.city, a2.city
375
+ assert_equal @spongebob_addr.state, a2.state
376
+ assert_equal @spongebob_addr.postal_code, a2.postal_code
377
+ end
378
+
379
+ def test_student_array_field
380
+ s = Student.new(:name => 'Spongebob Squarepants', :email => 'spongebob@example.com', :num_array => [100, 90, 80])
381
+ s.save
382
+
383
+ s2 = Student.find(:first)
384
+ assert_equal [100, 90, 80], s2.num_array
385
+ end
386
+
387
+ def test_has_many_initialize
388
+ s = Student.new(:name => 'Spongebob Squarepants', :email => 'spongebob@example.com', :scores => [@score1, @score2])
389
+ assert_not_nil s.scores
390
+ assert_equal 2, s.scores.length
391
+ assert_equal @score1, s.scores[0]
392
+ assert_equal @score2, s.scores[1]
393
+ end
394
+
395
+ def test_has_many_initialize_one_value
396
+ s = Student.new(:name => 'Spongebob Squarepants', :email => 'spongebob@example.com', :scores => @score1)
397
+ assert_not_nil s.scores
398
+ assert_equal 1, s.scores.length
399
+ assert_equal @score1, s.scores[0]
400
+ end
401
+
402
+ def test_has_many_save_and_find
403
+ s = Student.new(:name => 'Spongebob Squarepants', :email => 'spongebob@example.com', :scores => [@score1, @score2])
404
+ s.save!
405
+ assert_not_nil s.id
406
+
407
+ assert_equal 1, Student.count()
408
+ s2 = Student.find(:first)
409
+ assert_equal 'Spongebob Squarepants', s2.name
410
+ assert_equal 'spongebob@example.com', s2.email
411
+ list = s2.scores
412
+ assert_not_nil list
413
+ assert_equal 2, list.length
414
+ score = list.first
415
+ assert_not_nil score
416
+ assert_kind_of Score, score
417
+ assert (score.for_course.name == @score1.for_course.name && score.grade == @score1.grade), "oops: first score is wrong: #{score}"
418
+ end
419
+
420
+ def test_has_many_class_in_module
421
+ a1 = MyMod::A.new(:something => 4)
422
+ a2 = MyMod::A.new(:something => 10)
423
+ b = B.new(:a => [a1, a2])
424
+ assert_not_nil b.a
425
+ assert_equal 2, b.a.length
426
+ assert_equal a1, b.a[0]
427
+ assert_equal a2, b.a[1]
428
+ end
429
+
430
+ def test_field_query_methods
431
+ s = Student.new(:name => 'Spongebob Squarepants', :email => 'spongebob@example.com', :scores => [@score1, @score2])
432
+ assert s.name?
433
+ assert s.email?
434
+ assert s.scores
435
+
436
+ s = Student.new(:name => 'Spongebob Squarepants')
437
+ assert s.name?
438
+ assert !s.email?
439
+ assert !s.scores?
440
+
441
+ s.email = ''
442
+ assert !s.email?
443
+ end
444
+
445
+ def test_new_record
446
+ t = Track.new
447
+ assert_nil t.id
448
+ assert t.new_record?
449
+ t.save
450
+ assert_not_nil t.id
451
+ assert !t.new_record?
452
+
453
+ t = Track.create(:artist => 'Level 42', :album => 'Standing In The Light', :song => 'Micro-Kid', :track => 1)
454
+ assert !t.new_record?
455
+
456
+ t = Track.find(:first)
457
+ assert !t.new_record?
458
+
459
+ t = Track.find_or_create_by_song('New Song', :artist => 'New Artist', :album => 'New Album')
460
+ assert !t.new_record?
461
+
462
+ t = Track.find_or_initialize_by_song('Newer Song', :artist => 'Newer Artist', :album => 'Newer Album')
463
+ assert t.new_record?
464
+ end
465
+
466
+ def test_sql_parsing
467
+ t = Track.find(:first, :conditions => "song = '#{@mayor_song}'")
468
+ assert_equal @mayor_str, t.to_s
469
+ end
470
+
471
+ def test_sql_substitution
472
+ s = @mayor_song
473
+ t = Track.find(:first, :conditions => ["song = ?", s])
474
+ assert_equal @mayor_str, t.to_s
475
+ end
476
+
477
+ def test_sql_named_substitution
478
+ t = Track.find(:first, :conditions => ["song = :song", {:song => @mayor_song}])
479
+ assert_equal @mayor_str, t.to_s
480
+ end
481
+
482
+ def test_sql_like
483
+ t = Track.find(:first, :conditions => "song like '%Simp%'")
484
+ assert_equal @mayor_str, t.to_s
485
+ end
486
+
487
+ def test_sql_in
488
+ str = Track.find(:all, :conditions => "song in ('#{@mayor_song}', 'King For A Day')").inject('') { |str, t| str + t.to_s }
489
+ assert str.include?(@mayor_song)
490
+ assert str.include?('King For A Day')
491
+
492
+ list = Track.find(:all, :conditions => "track in (1,2,3)").to_a
493
+ assert_equal 3, list.length
494
+ assert_equal ['Garden Of Earthly Delights', 'King For A Day', @mayor_song], list.collect{|t| t.song}.sort
495
+ end
496
+
497
+ def test_in_array
498
+ str = Track.find(:all, :conditions => ["song in (?)", [@mayor_song, 'King For A Day']]).inject('') { |str, t| str + t.to_s }
499
+ assert str.include?(@mayor_song)
500
+ assert str.include?('King For A Day')
501
+ end
502
+
503
+ def test_in_array_rails_syntax
504
+ str = Track.find(:all, :conditions => {:song => [@mayor_song, 'King For A Day']}).inject('') { |str, t| str + t.to_s }
505
+ assert str.include?(@mayor_song)
506
+ assert str.include?('King For A Day')
507
+ end
508
+
509
+ def test_in_named_array
510
+ str = Track.find(:all, :conditions => ["song in (:songs)", {:songs => [@mayor_song, 'King For A Day']}]).inject('') { |str, t| str + t.to_s }
511
+ assert str.include?(@mayor_song)
512
+ assert str.include?('King For A Day')
513
+ end
514
+
515
+ def test_where
516
+ # function
517
+ str = Track.find(:all, :where => "function() { return obj.song == '#{@mayor_song}'; }").inject('') { |str, t| str + t.to_s }
518
+ assert_equal @mayor_str, str
519
+
520
+ # expression
521
+ str = Track.find(:all, :where => "obj.song == '#{@mayor_song}'").inject('') { |str, t| str + t.to_s }
522
+ assert_equal @mayor_str, str
523
+ end
524
+
525
+ def test_destroy
526
+ Track.destroy(@mayor_id)
527
+ begin
528
+ Track.find(@mayor_id)
529
+ fail "expected exception about missing ID"
530
+ rescue => ex
531
+ assert_match /Couldn't find Track with ID=#@mayor_id/, ex.to_s # ' <= for Emacs font lock mode
532
+ end
533
+ end
534
+
535
+ # Potential bug: if this test runs at midnight, a create runs before midnight
536
+ # and the update runs after, then this test will fail.
537
+ def test_time_updates
538
+ s = Student.new(:name => 'Spongebob Squarepants')
539
+ assert s.instance_variable_defined?(:@created_at)
540
+
541
+ assert !s.created_at?
542
+ assert !s.created_on?
543
+ assert !s.updated_on?
544
+
545
+ s.save
546
+ assert s.created_at?
547
+ assert_kind_of Time, s.created_at
548
+ assert s.created_on?
549
+ assert_kind_of Time, s.created_on
550
+ assert !s.updated_on?
551
+ t = Time.now
552
+ assert_equal Time.local(t.year, t.month, t.day), s.created_on
553
+
554
+ s.save
555
+ assert s.created_at?
556
+ assert s.created_on?
557
+ assert s.updated_on?
558
+ assert_kind_of Time, s.created_at
559
+ assert_equal s.created_on, s.updated_on
560
+ end
561
+
562
+ # This reproduces a bug where DBRefs weren't being created properly because
563
+ # the MongoRecord::Base objects weren't storing _ns
564
+ def test_db_ref
565
+ s = Student.new(:name => 'Spongebob Squarepants', :address => @spongebob_addr)
566
+ s.save
567
+
568
+ @course1.save
569
+ assert_not_nil @course1.id
570
+ assert_not_nil @course1["_ns"]
571
+
572
+ s.add_score(@course1.id, 3.5)
573
+ s.save
574
+
575
+ score = s.scores.first
576
+ assert_not_nil score
577
+ assert_equal @course1.name, score.for_course.name
578
+
579
+ # Now change the name of @course1 and see the student's score's course
580
+ # name change.
581
+ @course1.name = 'changed'
582
+ @course1.save
583
+
584
+ s = Student.find(:first, :conditions => "name = 'Spongebob Squarepants'")
585
+ assert_not_nil s
586
+ assert_equal 1, s.scores.length
587
+ assert_equal 'changed', s.scores.first.for_course.name
588
+
589
+
590
+ # Now try with has_many
591
+ score.save
592
+ s.scores = [score]
593
+ s.save
594
+
595
+ assert_equal 3.5, s.scores.first.grade
596
+
597
+ s = Student.find(:first, :conditions => "name = 'Spongebob Squarepants'")
598
+ assert_not_nil s
599
+ assert_equal 1, s.scores.length
600
+ assert_equal 3.5, s.scores.first.grade
601
+
602
+ score.grade = 4.0
603
+ score.save
604
+
605
+ s = Student.find(:first, :conditions => "name = 'Spongebob Squarepants'")
606
+ assert_not_nil s
607
+ assert_equal 1, s.scores.length
608
+ assert_equal 4.0, s.scores.first.grade
609
+ end
610
+
611
+ def test_subobjects_have_no_ids
612
+ @spongebob_addr.id
613
+ rescue => ex
614
+ assert_match /Subobjects don't have ids/, ex.to_s # ' <= for Emacs font-lock mode
615
+ end
616
+
617
+ def test_can_not_save_subobject
618
+ @spongebob_addr.save
619
+ fail "expected failed save of address"
620
+ rescue => ex
621
+ assert_match /Subobjects/, ex.to_s
622
+ end
623
+
624
+ def test_alternate_connection
625
+ old_db = MongoRecord::Base.connection
626
+ assert_equal @@db, old_db
627
+ alt_db = Mongo::Connection.new(@@host, @@port).db('mongorecord-test-alt-conn')
628
+ assert_not_equal old_db, alt_db
629
+ alt_db.drop_collection('students')
630
+ begin
631
+ @@db = nil
632
+ MongoRecord::Base.connection = alt_db
633
+ assert_equal alt_db, MongoRecord::Base.connection
634
+
635
+ # Make sure collection exists
636
+ coll = alt_db.collection('students')
637
+ coll.insert('name' => 'foo')
638
+ coll.clear
639
+
640
+ assert_equal 0, coll.count()
641
+ s = Student.new(:name => 'Spongebob Squarepants', :address => @spongebob_addr)
642
+ assert s.save, "save failed"
643
+ assert_equal 1, coll.count()
644
+ ensure
645
+ @@db = old_db
646
+ MongoRecord::Base.connection = @@db
647
+ alt_db.drop_collection('students')
648
+ end
649
+ end
650
+
651
+ def test_method_missing
652
+ begin
653
+ Track.foobar
654
+ fail "expected 'undefined method' exception"
655
+ rescue => ex
656
+ assert_match /undefined method \`foobar\' for Track:Class/, ex.to_s
657
+ end
658
+ end
659
+
660
+ def test_adding_custom_attributes
661
+ s = Student.new(:silly_name => 'Yowza!')
662
+ s.save
663
+ s = Student.last
664
+ assert_equal s.silly_name, 'Yowza!'
665
+ end
666
+
667
+ def assert_all_songs(str)
668
+ assert_match(/song: The Ability to Swing/, str)
669
+ assert_match(/song: Budapest by Blimp/, str)
670
+ assert_match(/song: Europa and the Pirate Twins/, str)
671
+ assert_match(/song: Garden Of Earthly Delights/, str)
672
+ assert_match(/song: The Mayor Of Simpleton/, str)
673
+ assert_match(/song: King For A Day/, str)
674
+ end
675
+
676
+
677
+ #################
678
+
679
+
680
+ def test_find_all_alias
681
+ assert_all_songs Track.all.inject('') { |str, t| str + t.to_s }
682
+ end
683
+
684
+ def test_find_first_alias
685
+ t = Track.first
686
+ assert t.kind_of?(Track)
687
+ str = t.to_s
688
+ assert_match(/artist: [^,]+,/, str, "did not find non-empty artist name")
689
+ end
690
+
691
+ def test_find_last
692
+ c = Course.new(:name=>"History")
693
+ c.save
694
+ assert_equal Course.last.name, "History"
695
+ end
696
+
697
+ def test_new_and_save_custom_attributes
698
+ x = Playlist.new(:artist => 'Level 42', :album => 'Standing In The Light', :song => 'Micro-Kid', :track => 1)
699
+ assert_nil(x.id)
700
+ x.save
701
+ x = Playlist.last
702
+ assert_not_nil(x.id)
703
+ assert_equal(x.artist, "Level 42")
704
+ assert_not_nil(x.created_at)
705
+ assert_not_nil(x.created_on)
706
+ end
707
+
708
+ def test_update_for_custom_attributes
709
+ p = Playlist.create(:artist => "The Beatles", :song => "Jailhouse Rock")
710
+ count = Playlist.count
711
+ p = Playlist.last
712
+ assert_equal(p.artist, "The Beatles")
713
+ p.artist = "Elvis"
714
+ p.save
715
+ assert_not_nil(p.updated_at)
716
+ assert_not_nil(p.updated_on)
717
+ assert_equal(count, Playlist.count)
718
+ end
719
+
720
+
721
+ def test_update_attributes
722
+ opts = {:artist => 'Bon Jovi', :album => 'Slippery When Wet', :song => 'Livin On A Prayer'}
723
+ track = Track.new
724
+ track.update_attributes(opts)
725
+ t = Track.find_by_artist("Bon Jovi")
726
+ assert_equal(t.album, "Slippery When Wet")
727
+ end
728
+
729
+ def test_update_attributes_for_custom_attributes
730
+ opts = {:artist => 'The Outfield', :album => 'Play Deep', :song => 'Your Love', :year => 1986}
731
+ playlist = Playlist.new
732
+ playlist.update_attributes(opts)
733
+ p = Playlist.find_by_artist("The Outfield")
734
+ assert_equal(p.year, 1986)
735
+ end
736
+
737
+ def test_custom_id
738
+ track = Track.new
739
+ track.id = 123
740
+ track.artist = "Nickleback"
741
+ track.song = "Rockstar"
742
+ track.save
743
+ p = Track.find(123)
744
+ assert_equal p.artist, "Nickleback"
745
+ end
746
+
747
+ def test_sum
748
+ Course.create(:name=>"Math", :student_count=>10)
749
+ Course.create(:name=>"Science", :student_count=>20)
750
+ assert_equal Course.sum("student_count"), 30
751
+ end
752
+
753
+ def test_indexing
754
+ Track.index :artist
755
+ Track.index [:artist, :created_at]
756
+ Track.index [:song, :desc], true
757
+ Track.index [:artist, [:album, :desc]]
758
+ Track.index [:created_at, Mongo::ASCENDING]
759
+
760
+ assert Track.indexes.has_key?("artist_1")
761
+ assert Track.indexes.has_key?("artist_1_created_at_1")
762
+ assert Track.indexes.has_key?("song_-1")
763
+ assert Track.indexes.has_key?("artist_1_album_-1")
764
+ assert Track.indexes.has_key?("created_at_1")
765
+ end
766
+
767
+ def test_subobject_create
768
+ Address.create(:street => "3 Pineapple Lane", :city => "Bikini Bottom", :state => "HI", :postal_code => "12345")
769
+ fail "expected can't create exception"
770
+ rescue => ex
771
+ assert_match /Subobjects can't be created/, ex.to_s
772
+ end
773
+
774
+ end