mongo_record 0.4.2

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.
@@ -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