API CHANGE Add :safe option for Collection#insert and Collection#save
The API change is minor: Collection#insert({...}, {...}, {...}) no longer works for inserting multiple documents - instead you must pass an explicit Array: Collection#insert([{...}, {...}, {...}])
This commit is contained in:
parent
7e0a1b9721
commit
6cb8c9f49b
|
@ -97,29 +97,50 @@ module XGen
|
|||
cursor.next_object # don't need to explicitly close b/c of limit
|
||||
end
|
||||
|
||||
# Save a document in this collection
|
||||
# Save a document in this collection.
|
||||
#
|
||||
# If +to_save+ already has an '_id' then an update (upsert) operation
|
||||
# is performed and any existing document with that _id is overwritten.
|
||||
# Otherwise an insert operation is performed.
|
||||
# Otherwise an insert operation is performed. Returns the _id of the
|
||||
# saved document.
|
||||
#
|
||||
# :to_save :: the document (a hash) to be saved
|
||||
def save(to_save)
|
||||
#
|
||||
# Options:
|
||||
# :safe :: if true, check that the save succeeded. OperationFailure
|
||||
# will be raised on an error. Checking for safety requires an extra
|
||||
# round-trip to the database
|
||||
def save(to_save, options={})
|
||||
if id = to_save[:_id] || to_save['_id']
|
||||
update({:_id => id}, to_save, :upsert => true)
|
||||
update({:_id => id}, to_save, :upsert => true, :safe => options.delete(:safe))
|
||||
id
|
||||
else
|
||||
insert(to_save)
|
||||
insert(to_save, :safe => options.delete(:safe))
|
||||
end
|
||||
end
|
||||
|
||||
# Insert +objects+, which are hashes. "<<" is aliased to this method.
|
||||
# Returns either the single inserted object or a new array containing
|
||||
# +objects+. The object(s) may have been modified by the database's PK
|
||||
# factory, if it has one.
|
||||
def insert(*objects)
|
||||
objects = objects.first if objects.size == 1 && objects.first.is_a?(Array)
|
||||
res = @db.insert_into_db(@name, objects)
|
||||
# Insert a document(s) into this collection.
|
||||
#
|
||||
# "<<" is aliased to this method. Returns the _id of the inserted
|
||||
# document or a list of _ids of the inserted documents. The object(s)
|
||||
# may have been modified by the database's PK factory, if it has one.
|
||||
#
|
||||
# :doc_or_docs :: a document (as a hash) or Array of documents to be
|
||||
# inserted
|
||||
#
|
||||
# Options:
|
||||
# :safe :: if true, check that the insert succeeded. OperationFailure
|
||||
# will be raised on an error. Checking for safety requires an extra
|
||||
# round-trip to the database
|
||||
def insert(doc_or_docs, options={})
|
||||
doc_or_docs = [doc_or_docs] if !doc_or_docs.is_a?(Array)
|
||||
res = @db.insert_into_db(@name, doc_or_docs)
|
||||
if options.delete(:safe)
|
||||
error = @db.error
|
||||
if error
|
||||
raise OperationFailure, error
|
||||
end
|
||||
end
|
||||
res.size > 1 ? res : res.first
|
||||
end
|
||||
alias_method :<<, :insert
|
||||
|
|
|
@ -491,8 +491,8 @@ module XGen
|
|||
end
|
||||
|
||||
# Insert +objects+ into +collection_name+. Normally called by
|
||||
# Collection#insert. Returns a new array containing +objects+,
|
||||
# possibly modified by @pk_factory.
|
||||
# Collection#insert. Returns a new array containing the _ids
|
||||
# of the inserted documents.
|
||||
def insert_into_db(collection_name, objects)
|
||||
_synchronize {
|
||||
if @pk_factory
|
||||
|
|
|
@ -31,6 +31,18 @@ class TestCollection < Test::Unit::TestCase
|
|||
@@test.drop()
|
||||
end
|
||||
|
||||
def test_safe_insert
|
||||
a = {"hello" => "world"}
|
||||
@@test.insert(a)
|
||||
a = @@test.find_first() # TODO we need this because insert doesn't add _id
|
||||
@@test.insert(a)
|
||||
assert @@db.error.include? "E11000"
|
||||
|
||||
assert_raise OperationFailure do
|
||||
@@test.insert(a, :safe => true)
|
||||
end
|
||||
end
|
||||
|
||||
def test_update
|
||||
id1 = @@test.save("x" => 5)
|
||||
@@test.update({}, {"$inc" => {"x" => 1}})
|
||||
|
@ -62,5 +74,17 @@ class TestCollection < Test::Unit::TestCase
|
|||
@@test.update({}, {"$inc" => {"x" => 1}}, :safe => true)
|
||||
end
|
||||
end
|
||||
|
||||
def test_safe_save
|
||||
@@test.create_index("hello", true)
|
||||
|
||||
@@test.save("hello" => "world")
|
||||
@@test.save("hello" => "world")
|
||||
assert @@db.error.include? "E11000"
|
||||
|
||||
assert_raise OperationFailure do
|
||||
@@test.save({"hello" => "world"}, :safe => true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class DBAPITest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_insert_multiple
|
||||
ids = @@coll.insert({'a' => 2}, {'b' => 3})
|
||||
ids = @@coll.insert([{'a' => 2}, {'b' => 3}])
|
||||
|
||||
ids.each do |i|
|
||||
assert_kind_of ObjectID, i
|
||||
|
|
Loading…
Reference in New Issue