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.
- data/LICENSE +202 -0
- data/README.rdoc +85 -0
- data/Rakefile +38 -0
- data/examples/tracks.rb +109 -0
- data/lib/mongo_record/base.rb +988 -0
- data/lib/mongo_record/convert.rb +64 -0
- data/lib/mongo_record/log_device.rb +111 -0
- data/lib/mongo_record/sql.rb +235 -0
- data/lib/mongo_record/subobject.rb +109 -0
- data/lib/mongo_record.rb +21 -0
- data/mongo-activerecord-ruby.gemspec +38 -0
- data/tests/address.rb +12 -0
- data/tests/class_in_module.rb +11 -0
- data/tests/course.rb +10 -0
- data/tests/student.rb +34 -0
- data/tests/test_log_device.rb +82 -0
- data/tests/test_mongo.rb +774 -0
- data/tests/test_sql.rb +176 -0
- data/tests/track2.rb +9 -0
- data/tests/track3.rb +9 -0
- metadata +85 -0
data/tests/test_mongo.rb
ADDED
@@ -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
|