Fixed side effect bug

pull/2/head
Louis Chatriot 9 years ago
parent ef8905adf0
commit 7b3f3c2868
  1. 27
      lib/datastore.js
  2. 40
      test/db.test.js

@ -34,6 +34,7 @@ function Datastore (options) {
filename = options.filename;
this.inMemoryOnly = options.inMemoryOnly || false;
this.autoload = options.autoload || false;
this.timestampData = options.timestampData || false;
}
// Determine whether in memory or persistent
@ -283,17 +284,19 @@ Datastore.prototype.getCandidates = function (query) {
*/
Datastore.prototype._insert = function (newDoc, cb) {
var callback = cb || function () {}
, preparedDoc
;
try {
this._insertInCache(newDoc);
preparedDoc = this.prepareDocumentForInsertion(newDoc)
this._insertInCache(preparedDoc);
} catch (e) {
return callback(e);
}
this.persistence.persistNewState(util.isArray(newDoc) ? newDoc : [newDoc], function (err) {
this.persistence.persistNewState(util.isArray(preparedDoc) ? preparedDoc : [preparedDoc], function (err) {
if (err) { return callback(err); }
return callback(null, newDoc);
return callback(null, model.deepCopy(preparedDoc));
});
};
@ -311,6 +314,7 @@ Datastore.prototype.createNewId = function () {
/**
* Prepare a document (or array of documents) to be inserted in a database
* Meaning adds _id and createdAt if necessary on a copy of newDoc to avoid any side effect on user input
* @api private
*/
Datastore.prototype.prepareDocumentForInsertion = function (newDoc) {
@ -320,9 +324,8 @@ Datastore.prototype.prepareDocumentForInsertion = function (newDoc) {
preparedDoc = [];
newDoc.forEach(function (doc) { preparedDoc.push(self.prepareDocumentForInsertion(doc)); });
} else {
if (newDoc._id === undefined) { newDoc._id = this.createNewId(); }
preparedDoc = model.deepCopy(newDoc);
//if (preparedDoc._id === undefined) { preparedDoc._id = this.createNewId(); }
if (preparedDoc._id === undefined) { preparedDoc._id = this.createNewId(); }
if (this.timestampData && preparedDoc.createdAt === undefined) { preparedDoc.createdAt = new Date(); }
model.checkObject(preparedDoc);
}
@ -334,11 +337,11 @@ Datastore.prototype.prepareDocumentForInsertion = function (newDoc) {
* If newDoc is an array of documents, this will insert all documents in the cache
* @api private
*/
Datastore.prototype._insertInCache = function (newDoc) {
if (util.isArray(newDoc)) {
this._insertMultipleDocsInCache(newDoc);
Datastore.prototype._insertInCache = function (preparedDoc) {
if (util.isArray(preparedDoc)) {
this._insertMultipleDocsInCache(preparedDoc);
} else {
this.addToIndexes(this.prepareDocumentForInsertion(newDoc));
this.addToIndexes(preparedDoc);
}
};
@ -347,10 +350,8 @@ Datastore.prototype._insertInCache = function (newDoc) {
* inserts and throws the error
* @api private
*/
Datastore.prototype._insertMultipleDocsInCache = function (newDocs) {
var i, failingI, error
, preparedDocs = this.prepareDocumentForInsertion(newDocs)
;
Datastore.prototype._insertMultipleDocsInCache = function (preparedDocs) {
var i, failingI, error;
for (i = 0; i < preparedDocs.length; i += 1) {
try {

@ -265,10 +265,48 @@ describe('Database', function () {
done();
});
});
});
});
it("If timestampData option is set, a createdAt field is added and persisted", function (done) {
var newDoc = { hello: 'world' }, beginning = Date.now();
d = new Datastore({ filename: testDb, timestampData: true, autoload: true });
d.find({}, function (err, docs) {
assert.isNull(err);
docs.length.should.equal(0);
d.insert(newDoc, function (err, insertedDoc) {
// No side effect on given input
assert.deepEqual(newDoc, { hello: 'world' });
// Insert doc has two new fields, _id and createdAt
insertedDoc.hello.should.equal('world');
assert.isDefined(insertedDoc.createdAt);
assert.isDefined(insertedDoc._id);
Object.keys(insertedDoc).length.should.equal(3);
assert.isBelow(Math.abs(insertedDoc.createdAt.getTime() - beginning), 15); // No more than 15ms should have elapsed
});
// Modifying results of insert doesn't change the cache
insertedDoc.bloup = "another";
Object.keys(insertedDoc).length.should.equal(4);
d.find({}, function (err, docs) {
docs.length.should.equal(1);
assert.deepEqual(newDoc, { hello: 'world' });
assert.deepEqual({ hello: 'world', _id: insertedDoc._id, createdAt: insertedDoc.createdAt }, docs[0]);
// All data correctly persisted on disk
d.loadDatabase(function () {
d.find({}, function (err, docs) {
docs.length.should.equal(1);
assert.deepEqual(newDoc, { hello: 'world' });
assert.deepEqual({ hello: 'world', _id: insertedDoc._id, createdAt: insertedDoc.createdAt }, docs[0]);
done();
});
});
});
});
});
});
it('Can insert a doc with id 0', function (done) {

Loading…
Cancel
Save