mongodb-mongo 0.8 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +7 -0
- data/lib/mongo/collection.rb +8 -11
- data/lib/mongo/db.rb +21 -31
- data/lib/mongo/message/insert_message.rb +2 -2
- data/lib/mongo/message/message.rb +3 -3
- data/lib/mongo/util/bson.rb +52 -43
- data/mongo-ruby-driver.gemspec +1 -1
- data/tests/test_db_api.rb +114 -14
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -324,6 +324,13 @@ Adrian Madrid, aemadrid@gmail.com
|
|
324
324
|
Aman Gupta, aman@tmm1.net
|
325
325
|
* Collection#save
|
326
326
|
|
327
|
+
Jon Crosby, jon@joncrosby.me
|
328
|
+
* Some code clean-up
|
329
|
+
|
330
|
+
John Nunemaker, http://railstips.org
|
331
|
+
* Collection#create_index takes symbols as well as strings
|
332
|
+
* Fix for Collection#save
|
333
|
+
|
327
334
|
= License
|
328
335
|
|
329
336
|
Copyright 2008-2009 10gen Inc.
|
data/lib/mongo/collection.rb
CHANGED
@@ -76,7 +76,7 @@ module XGen
|
|
76
76
|
# Save an updated +object+ to the collection, or insert it if it doesn't exist already.
|
77
77
|
def save(object)
|
78
78
|
if id = object[:_id] || object['_id']
|
79
|
-
|
79
|
+
repsert({:_id => id}, object)
|
80
80
|
else
|
81
81
|
insert(object)
|
82
82
|
end
|
@@ -171,10 +171,11 @@ function () {
|
|
171
171
|
key[keys[i]] = obj[keys[i]];
|
172
172
|
}
|
173
173
|
|
174
|
-
var aggObj = map
|
174
|
+
var aggObj = map.get(key);
|
175
175
|
if (aggObj == null) {
|
176
176
|
var newObj = Object.extend({}, key);
|
177
|
-
aggObj =
|
177
|
+
aggObj = Object.extend(newObj, initial);
|
178
|
+
map.put(key, aggObj);
|
178
179
|
}
|
179
180
|
reduce_function(obj, aggObj);
|
180
181
|
}
|
@@ -190,14 +191,10 @@ EOS
|
|
190
191
|
}))["result"]
|
191
192
|
end
|
192
193
|
|
193
|
-
#
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
# :keys :: Hash whose keys are the names of the fields that make up
|
198
|
-
# the key and values are integers.
|
199
|
-
#
|
200
|
-
# :ns :: Namespace; same as this collection's name.
|
194
|
+
# Get information on the indexes for the collection +collection_name+.
|
195
|
+
# Returns a hash where the keys are index names (as returned by
|
196
|
+
# Collection#create_index and the values are lists of [key, direction]
|
197
|
+
# pairs specifying the index (as passed to Collection#create_index).
|
201
198
|
def index_information
|
202
199
|
@db.index_information(@name)
|
203
200
|
end
|
data/lib/mongo/db.rb
CHANGED
@@ -390,6 +390,7 @@ module XGen
|
|
390
390
|
oh[:query] = selector || {}
|
391
391
|
doc = db_command(oh)
|
392
392
|
return doc['n'].to_i if ok?(doc)
|
393
|
+
return 0 if doc['errmsg'] == "ns missing"
|
393
394
|
raise "Error with count command: #{doc.inspect}"
|
394
395
|
end
|
395
396
|
|
@@ -425,31 +426,18 @@ module XGen
|
|
425
426
|
raise "Error with drop_index command: #{doc.inspect}" unless ok?(doc)
|
426
427
|
end
|
427
428
|
|
428
|
-
#
|
429
|
-
# Normally called by Collection#index_information.
|
430
|
-
#
|
431
|
-
#
|
432
|
-
#
|
433
|
-
# :keys :: Hash whose keys are the names of the fields that make up
|
434
|
-
# the key and values are integers.
|
435
|
-
#
|
436
|
-
# :ns :: Namespace; same as +collection_name+.
|
429
|
+
# Get information on the indexes for the collection +collection_name+.
|
430
|
+
# Normally called by Collection#index_information. Returns a hash where
|
431
|
+
# the keys are index names (as returned by Collection#create_index and
|
432
|
+
# the values are lists of [key, direction] pairs specifying the index
|
433
|
+
# (as passed to Collection#create_index).
|
437
434
|
def index_information(collection_name)
|
438
435
|
sel = {:ns => full_coll_name(collection_name)}
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
h[:keys] = row['key']
|
444
|
-
raise "Keys for index on return from db was nil. Coll = #{full_coll_name(collection_name)}" unless h[:keys]
|
445
|
-
|
446
|
-
h[:ns] = row['ns']
|
447
|
-
raise "Namespace for index on return from db was nil. Coll = #{full_coll_name(collection_name)}" unless h[:ns]
|
448
|
-
h[:ns].sub!(/.*\./, '')
|
449
|
-
raise "Error: ns != collection" unless h[:ns] == collection_name
|
450
|
-
|
451
|
-
h
|
436
|
+
info = {}
|
437
|
+
query(Collection.new(self, SYSTEM_INDEX_COLLECTION), Query.new(sel)).each { |index|
|
438
|
+
info[index['name']] = index['key'].to_a
|
452
439
|
}
|
440
|
+
info
|
453
441
|
end
|
454
442
|
|
455
443
|
# Create a new index on +collection_name+. +field_or_spec+
|
@@ -460,10 +448,10 @@ module XGen
|
|
460
448
|
# enforce a uniqueness constraint.
|
461
449
|
def create_index(collection_name, field_or_spec, unique=false)
|
462
450
|
field_h = OrderedHash.new
|
463
|
-
if field_or_spec.is_a?
|
464
|
-
field_h[field_or_spec] = 1
|
451
|
+
if field_or_spec.is_a?(String) || field_or_spec.is_a?(Symbol)
|
452
|
+
field_h[field_or_spec.to_s] = 1
|
465
453
|
else
|
466
|
-
field_or_spec.each { |f| field_h[f[0]] = f[1] }
|
454
|
+
field_or_spec.each { |f| field_h[f[0].to_s] = f[1] }
|
467
455
|
end
|
468
456
|
name = gen_index_name(field_h)
|
469
457
|
sel = {
|
@@ -473,7 +461,7 @@ module XGen
|
|
473
461
|
:unique => unique
|
474
462
|
}
|
475
463
|
@semaphore.synchronize {
|
476
|
-
send_to_db(InsertMessage.new(@name, SYSTEM_INDEX_COLLECTION, sel))
|
464
|
+
send_to_db(InsertMessage.new(@name, SYSTEM_INDEX_COLLECTION, false, sel))
|
477
465
|
}
|
478
466
|
name
|
479
467
|
end
|
@@ -483,11 +471,13 @@ module XGen
|
|
483
471
|
# possibly modified by @pk_factory.
|
484
472
|
def insert_into_db(collection_name, objects)
|
485
473
|
@semaphore.synchronize {
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
474
|
+
if @pk_factory
|
475
|
+
objects.collect! { |o|
|
476
|
+
@pk_factory.create_pk(o)
|
477
|
+
}
|
478
|
+
end
|
479
|
+
send_to_db(InsertMessage.new(@name, collection_name, true, *objects))
|
480
|
+
objects
|
491
481
|
}
|
492
482
|
end
|
493
483
|
|
@@ -23,11 +23,11 @@ module XGen
|
|
23
23
|
|
24
24
|
class InsertMessage < Message
|
25
25
|
|
26
|
-
def initialize(db_name, collection_name, *objs)
|
26
|
+
def initialize(db_name, collection_name, check_keys=true, *objs)
|
27
27
|
super(OP_INSERT)
|
28
28
|
write_int(0)
|
29
29
|
write_string("#{db_name}.#{collection_name}")
|
30
|
-
objs.each { |o| write_doc(o) }
|
30
|
+
objs.each { |o| write_doc(o, check_keys) }
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -36,7 +36,7 @@ module XGen
|
|
36
36
|
@request_id = (@@class_req_id += 1)
|
37
37
|
@response_id = 0
|
38
38
|
@buf = ByteBuffer.new
|
39
|
-
|
39
|
+
|
40
40
|
@buf.put_int(16) # holder for length
|
41
41
|
@buf.put_int(@request_id)
|
42
42
|
@buf.put_int(0) # response_to
|
@@ -58,8 +58,8 @@ module XGen
|
|
58
58
|
update_message_length
|
59
59
|
end
|
60
60
|
|
61
|
-
def write_doc(hash)
|
62
|
-
@buf.put_array(BSON.new.serialize(hash).to_a)
|
61
|
+
def write_doc(hash, check_keys=false)
|
62
|
+
@buf.put_array(BSON.new.serialize(hash, check_keys).to_a)
|
63
63
|
update_message_length
|
64
64
|
end
|
65
65
|
|
data/lib/mongo/util/bson.rb
CHANGED
@@ -73,11 +73,11 @@ class BSON
|
|
73
73
|
|
74
74
|
begin
|
75
75
|
require 'mongo_ext/cbson'
|
76
|
-
def serialize(obj)
|
77
|
-
@buf = ByteBuffer.new(CBson.serialize(obj))
|
76
|
+
def serialize(obj, check_keys=false)
|
77
|
+
@buf = ByteBuffer.new(CBson.serialize(obj, check_keys))
|
78
78
|
end
|
79
79
|
rescue LoadError
|
80
|
-
def serialize(obj)
|
80
|
+
def serialize(obj, check_keys=false)
|
81
81
|
raise "Document is null" unless obj
|
82
82
|
|
83
83
|
@buf.rewind
|
@@ -86,12 +86,12 @@ class BSON
|
|
86
86
|
|
87
87
|
# Write key/value pairs. Always write _id first if it exists.
|
88
88
|
if obj.has_key? '_id'
|
89
|
-
serialize_key_value('_id', obj['_id'])
|
89
|
+
serialize_key_value('_id', obj['_id'], check_keys)
|
90
90
|
elsif obj.has_key? :_id
|
91
|
-
serialize_key_value('_id', obj[:_id])
|
91
|
+
serialize_key_value('_id', obj[:_id], check_keys)
|
92
92
|
end
|
93
93
|
|
94
|
-
obj.each {|k, v| serialize_key_value(k, v) unless k == '_id' || k == :_id }
|
94
|
+
obj.each {|k, v| serialize_key_value(k, v, check_keys) unless k == '_id' || k == :_id }
|
95
95
|
|
96
96
|
serialize_eoo_element(@buf)
|
97
97
|
@buf.put_int(@buf.size, 0)
|
@@ -99,38 +99,47 @@ class BSON
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
def serialize_key_value(k, v)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
serialize_object_element(@buf, k, v)
|
111
|
-
when OID
|
112
|
-
serialize_oid_element(@buf, k, v)
|
113
|
-
when ARRAY
|
114
|
-
serialize_array_element(@buf, k, v)
|
115
|
-
when REGEX
|
116
|
-
serialize_regex_element(@buf, k, v)
|
117
|
-
when BOOLEAN
|
118
|
-
serialize_boolean_element(@buf, k, v)
|
119
|
-
when DATE
|
120
|
-
serialize_date_element(@buf, k, v)
|
121
|
-
when NULL
|
122
|
-
serialize_null_element(@buf, k)
|
123
|
-
when REF
|
124
|
-
serialize_dbref_element(@buf, k, v)
|
125
|
-
when BINARY
|
126
|
-
serialize_binary_element(@buf, k, v)
|
127
|
-
when UNDEFINED
|
128
|
-
serialize_undefined_element(@buf, k)
|
129
|
-
when CODE_W_SCOPE
|
130
|
-
serialize_code_w_scope(@buf, k, v)
|
131
|
-
else
|
132
|
-
raise "unhandled type #{type}"
|
102
|
+
def serialize_key_value(k, v, check_keys)
|
103
|
+
k = k.to_s
|
104
|
+
if check_keys
|
105
|
+
if k[0] == ?$
|
106
|
+
raise RuntimeError.new("key #{k} must not start with '$'")
|
107
|
+
end
|
108
|
+
if k.include? ?.
|
109
|
+
raise RuntimeError.new("key #{k} must not contain '.'")
|
133
110
|
end
|
111
|
+
end
|
112
|
+
type = bson_type(v)
|
113
|
+
case type
|
114
|
+
when STRING, SYMBOL
|
115
|
+
serialize_string_element(@buf, k, v, type)
|
116
|
+
when NUMBER, NUMBER_INT
|
117
|
+
serialize_number_element(@buf, k, v, type)
|
118
|
+
when OBJECT
|
119
|
+
serialize_object_element(@buf, k, v, check_keys)
|
120
|
+
when OID
|
121
|
+
serialize_oid_element(@buf, k, v)
|
122
|
+
when ARRAY
|
123
|
+
serialize_array_element(@buf, k, v, check_keys)
|
124
|
+
when REGEX
|
125
|
+
serialize_regex_element(@buf, k, v)
|
126
|
+
when BOOLEAN
|
127
|
+
serialize_boolean_element(@buf, k, v)
|
128
|
+
when DATE
|
129
|
+
serialize_date_element(@buf, k, v)
|
130
|
+
when NULL
|
131
|
+
serialize_null_element(@buf, k)
|
132
|
+
when REF
|
133
|
+
serialize_dbref_element(@buf, k, v)
|
134
|
+
when BINARY
|
135
|
+
serialize_binary_element(@buf, k, v)
|
136
|
+
when UNDEFINED
|
137
|
+
serialize_undefined_element(@buf, k)
|
138
|
+
when CODE_W_SCOPE
|
139
|
+
serialize_code_w_scope(@buf, k, v)
|
140
|
+
else
|
141
|
+
raise "unhandled type #{type}"
|
142
|
+
end
|
134
143
|
end
|
135
144
|
|
136
145
|
begin
|
@@ -344,7 +353,7 @@ class BSON
|
|
344
353
|
oh = OrderedHash.new
|
345
354
|
oh['$ref'] = val.namespace
|
346
355
|
oh['$id'] = val.object_id
|
347
|
-
serialize_object_element(buf, key, oh)
|
356
|
+
serialize_object_element(buf, key, oh, false)
|
348
357
|
end
|
349
358
|
|
350
359
|
def serialize_binary_element(buf, key, val)
|
@@ -391,24 +400,24 @@ class BSON
|
|
391
400
|
buf.put_double(val)
|
392
401
|
else
|
393
402
|
if val > 2**32 / 2 - 1 or val < -2**32 / 2
|
394
|
-
raise RangeError.new
|
403
|
+
raise RangeError.new("MongoDB can only handle 4-byte ints - try converting to a double before saving")
|
395
404
|
end
|
396
405
|
buf.put_int(val)
|
397
406
|
end
|
398
407
|
end
|
399
408
|
|
400
|
-
def serialize_object_element(buf, key, val, opcode=OBJECT)
|
409
|
+
def serialize_object_element(buf, key, val, check_keys, opcode=OBJECT)
|
401
410
|
buf.put(opcode)
|
402
411
|
self.class.serialize_cstr(buf, key)
|
403
|
-
buf.put_array(BSON.new.serialize(val).to_a)
|
412
|
+
buf.put_array(BSON.new.serialize(val, check_keys).to_a)
|
404
413
|
end
|
405
414
|
|
406
|
-
def serialize_array_element(buf, key, val)
|
415
|
+
def serialize_array_element(buf, key, val, check_keys)
|
407
416
|
# Turn array into hash with integer indices as keys
|
408
417
|
h = OrderedHash.new
|
409
418
|
i = 0
|
410
419
|
val.each { |v| h[i] = v; i += 1 }
|
411
|
-
serialize_object_element(buf, key, h, ARRAY)
|
420
|
+
serialize_object_element(buf, key, h, check_keys, ARRAY)
|
412
421
|
end
|
413
422
|
|
414
423
|
def serialize_regex_element(buf, key, val)
|
data/mongo-ruby-driver.gemspec
CHANGED
@@ -79,7 +79,7 @@ TEST_FILES = ['tests/mongo-qa/_common.rb',
|
|
79
79
|
|
80
80
|
Gem::Specification.new do |s|
|
81
81
|
s.name = 'mongo'
|
82
|
-
s.version = '0.
|
82
|
+
s.version = '0.9'
|
83
83
|
s.platform = Gem::Platform::RUBY
|
84
84
|
s.summary = 'Ruby driver for the 10gen Mongo DB'
|
85
85
|
s.description = 'A Ruby driver for the 10gen Mongo DB. For more information about Mongo, see http://www.mongodb.org.'
|
data/tests/test_db_api.rb
CHANGED
@@ -56,6 +56,11 @@ class DBAPITest < Test::Unit::TestCase
|
|
56
56
|
assert docs.detect { |row| row['b'] == 3 }
|
57
57
|
end
|
58
58
|
|
59
|
+
def test_count_on_nonexisting
|
60
|
+
@@db.drop_collection('foo')
|
61
|
+
assert_equal 0, @@db.collection('foo').count()
|
62
|
+
end
|
63
|
+
|
59
64
|
def test_find_simple
|
60
65
|
@r2 = @@coll.insert('a' => 2)
|
61
66
|
@r3 = @@coll.insert('b' => 3)
|
@@ -282,29 +287,55 @@ class DBAPITest < Test::Unit::TestCase
|
|
282
287
|
end
|
283
288
|
|
284
289
|
def test_index_information
|
290
|
+
assert_equal @@coll.index_information.length, 1
|
291
|
+
|
285
292
|
name = @@db.create_index(@@coll.name, 'a')
|
286
|
-
|
287
|
-
assert_equal
|
288
|
-
assert_equal
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
assert_equal name,
|
293
|
-
|
293
|
+
info = @@db.index_information(@@coll.name)
|
294
|
+
assert_equal name, "a_1"
|
295
|
+
assert_equal @@coll.index_information, info
|
296
|
+
assert_equal 2, info.length
|
297
|
+
|
298
|
+
assert info.has_key?(name)
|
299
|
+
assert_equal info[name], [["a", ASCENDING]]
|
300
|
+
ensure
|
301
|
+
@@db.drop_index(@@coll.name, name)
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_index_create_with_symbol
|
305
|
+
assert_equal @@coll.index_information.length, 1
|
306
|
+
|
307
|
+
name = @@db.create_index(@@coll.name, :a)
|
308
|
+
info = @@db.index_information(@@coll.name)
|
309
|
+
assert_equal name, "a_1"
|
310
|
+
assert_equal @@coll.index_information, info
|
311
|
+
assert_equal 2, info.length
|
312
|
+
|
313
|
+
assert info.has_key?(name)
|
314
|
+
assert_equal info[name], [["a", ASCENDING]]
|
294
315
|
ensure
|
295
316
|
@@db.drop_index(@@coll.name, name)
|
296
317
|
end
|
297
318
|
|
298
319
|
def test_multiple_index_cols
|
299
320
|
name = @@db.create_index(@@coll.name, [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]])
|
300
|
-
|
301
|
-
assert_equal 2,
|
321
|
+
info = @@db.index_information(@@coll.name)
|
322
|
+
assert_equal 2, info.length
|
323
|
+
|
324
|
+
assert_equal name, 'a_-1_b_1_c_-1'
|
325
|
+
assert info.has_key?(name)
|
326
|
+
assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
|
327
|
+
ensure
|
328
|
+
@@db.drop_index(@@coll.name, name)
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_multiple_index_cols_with_symbols
|
332
|
+
name = @@db.create_index(@@coll.name, [[:a, DESCENDING], [:b, ASCENDING], [:c, DESCENDING]])
|
333
|
+
info = @@db.index_information(@@coll.name)
|
334
|
+
assert_equal 2, info.length
|
302
335
|
|
303
|
-
info = list[1]
|
304
336
|
assert_equal name, 'a_-1_b_1_c_-1'
|
305
|
-
|
306
|
-
|
307
|
-
assert_equal ['a', 'b', 'c'], keys.sort
|
337
|
+
assert info.has_key?(name)
|
338
|
+
assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
|
308
339
|
ensure
|
309
340
|
@@db.drop_index(@@coll.name, name)
|
310
341
|
end
|
@@ -327,8 +358,25 @@ class DBAPITest < Test::Unit::TestCase
|
|
327
358
|
test.insert("hello" => "mike")
|
328
359
|
test.insert("hello" => "world")
|
329
360
|
assert @@db.error?
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_index_on_subfield
|
364
|
+
@@db.drop_collection("blah")
|
365
|
+
test = @@db.collection("blah")
|
366
|
+
|
367
|
+
test.insert("hello" => {"a" => 4, "b" => 5})
|
368
|
+
test.insert("hello" => {"a" => 7, "b" => 2})
|
369
|
+
test.insert("hello" => {"a" => 4, "b" => 10})
|
370
|
+
assert !@@db.error?
|
330
371
|
|
331
372
|
@@db.drop_collection("blah")
|
373
|
+
test = @@db.collection("blah")
|
374
|
+
test.create_index("hello.a", unique=true)
|
375
|
+
|
376
|
+
test.insert("hello" => {"a" => 4, "b" => 5})
|
377
|
+
test.insert("hello" => {"a" => 7, "b" => 2})
|
378
|
+
test.insert("hello" => {"a" => 4, "b" => 10})
|
379
|
+
assert @@db.error?
|
332
380
|
end
|
333
381
|
|
334
382
|
def test_array
|
@@ -585,6 +633,58 @@ class DBAPITest < Test::Unit::TestCase
|
|
585
633
|
assert_equal 2, @@coll.count
|
586
634
|
end
|
587
635
|
|
636
|
+
def test_save_with_object_that_has_id_but_does_not_actually_exist_in_collection
|
637
|
+
@@coll.clear
|
638
|
+
|
639
|
+
a = {'_id' => '1', 'hello' => 'world'}
|
640
|
+
@@coll.save(a)
|
641
|
+
assert_equal(1, @@coll.count)
|
642
|
+
assert_equal("world", @@coll.find_first()["hello"])
|
643
|
+
|
644
|
+
a["hello"] = "mike"
|
645
|
+
@@coll.save(a)
|
646
|
+
assert_equal(1, @@coll.count)
|
647
|
+
assert_equal("mike", @@coll.find_first()["hello"])
|
648
|
+
end
|
649
|
+
|
650
|
+
def test_invalid_key_names
|
651
|
+
@@coll.clear
|
652
|
+
|
653
|
+
@@coll.insert({"hello" => "world"})
|
654
|
+
@@coll.insert({"hello" => {"hello" => "world"}})
|
655
|
+
|
656
|
+
assert_raise RuntimeError do
|
657
|
+
@@coll.insert({"$hello" => "world"})
|
658
|
+
end
|
659
|
+
assert_raise RuntimeError do
|
660
|
+
@@coll.insert({"hello" => {"$hello" => "world"}})
|
661
|
+
end
|
662
|
+
|
663
|
+
@@coll.insert({"he$llo" => "world"})
|
664
|
+
@@coll.insert({"hello" => {"hell$o" => "world"}})
|
665
|
+
|
666
|
+
assert_raise RuntimeError do
|
667
|
+
@@coll.insert({".hello" => "world"})
|
668
|
+
end
|
669
|
+
assert_raise RuntimeError do
|
670
|
+
@@coll.insert({"hello" => {".hello" => "world"}})
|
671
|
+
end
|
672
|
+
assert_raise RuntimeError do
|
673
|
+
@@coll.insert({"hello." => "world"})
|
674
|
+
end
|
675
|
+
assert_raise RuntimeError do
|
676
|
+
@@coll.insert({"hello" => {"hello." => "world"}})
|
677
|
+
end
|
678
|
+
assert_raise RuntimeError do
|
679
|
+
@@coll.insert({"hel.lo" => "world"})
|
680
|
+
end
|
681
|
+
assert_raise RuntimeError do
|
682
|
+
@@coll.insert({"hello" => {"hel.lo" => "world"}})
|
683
|
+
end
|
684
|
+
|
685
|
+
@@coll.modify({"hello" => "world"}, {"$inc" => "hello"})
|
686
|
+
end
|
687
|
+
|
588
688
|
# TODO this test fails with error message "Undefed Before end of object"
|
589
689
|
# That is a database error. The undefined type may go away.
|
590
690
|
|