diff --git a/lib/datastore.js b/lib/datastore.js index 5368249..64334af 100644 --- a/lib/datastore.js +++ b/lib/datastore.js @@ -55,6 +55,7 @@ Datastore.prototype.loadDatabase = function () { executor.push({ this: this, fn: this._loadDatabase, arguments: arguments }); }; + /** * From a database's raw data, return the corresponding * machine understandable collection @@ -70,7 +71,13 @@ Datastore.treatRawData = function (rawData) { try { doc = model.deserialize(data[i]); - if (doc._id) { dataById[doc._id] = doc; } + if (doc._id) { + if (doc.$$deleted === true) { + delete dataById[doc._id]; + } else { + dataById[doc._id] = doc; + } + } } catch (e) { } } diff --git a/lib/model.js b/lib/model.js index d8edec1..ef19df8 100644 --- a/lib/model.js +++ b/lib/model.js @@ -18,12 +18,12 @@ var dateToJSON = function () { return { $$date: this.getTime() }; } * Check a key, throw an error if the key is non valid * @param {String} k key * @param {Model} v value, needed to treat the Date edge case - * Non-treatable edge case here: if part of the object if of the form { $$date: number } + * Non-treatable edge cases here: if part of the object if of the form { $$date: number } or { $$deleted: true } * Its serialized-then-deserialized version it will transformed into a Date object * But you really need to want it to trigger such behaviour, even when warned not to use '$' at the beginning of the field names... */ function checkKey (k, v) { - if (k[0] === '$' && !(k === '$$date' && typeof v === 'number')) { + if (k[0] === '$' && !(k === '$$date' && typeof v === 'number') && !(k === '$$deleted' && v === true)) { throw 'Field names cannot begin with the $ character'; } diff --git a/test/db.test.js b/test/db.test.js index 66b10c9..13fe723 100644 --- a/test/db.test.js +++ b/test/db.test.js @@ -36,7 +36,7 @@ describe('Database', function () { }); - describe.only('Loading the database data from file', function () { + describe('Loading the database data from file', function () { it('Every line represents a document', function () { var now = new Date() @@ -95,6 +95,35 @@ describe('Database', function () { _.isEqual(treatedData[1], { _id: "2", hello: 'world' }).should.equal(true); }); + it('If a doc contains $$deleted: true, that means we need to remove it from the data', function () { + var now = new Date() + , rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + + model.serialize({ _id: "2", hello: 'world' }) + '\n' + + model.serialize({ _id: "1", $$deleted: true }) + '\n' + + model.serialize({ _id: "3", today: now }) + , treatedData = Datastore.treatRawData(rawData) + ; + + treatedData.sort(function (a, b) { return a._id - b._id; }); + treatedData.length.should.equal(2); + _.isEqual(treatedData[0], { _id: "2", hello: 'world' }).should.equal(true); + _.isEqual(treatedData[1], { _id: "3", today: now }).should.equal(true); + }); + + it('If a doc contains $$deleted: true, no error is thrown if the doc wasnt in the list before', function () { + var now = new Date() + , rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + + model.serialize({ _id: "2", $$deleted: true }) + '\n' + + model.serialize({ _id: "3", today: now }) + , treatedData = Datastore.treatRawData(rawData) + ; + + treatedData.sort(function (a, b) { return a._id - b._id; }); + treatedData.length.should.equal(2); + _.isEqual(treatedData[0], { _id: "1", a: 2, ages: [1, 5, 12] }).should.equal(true); + _.isEqual(treatedData[1], { _id: "3", today: now }).should.equal(true); + }); + }); // ==== End of 'Loading the database data from file' ==== //