diff --git a/lib/model.js b/lib/model.js index 9752814..0e94e9a 100644 --- a/lib/model.js +++ b/lib/model.js @@ -223,12 +223,17 @@ function compareThings (a, b) { * @param {Model} value */ -// Set a field to a new value +/** + * Set a field to a new value + */ lastStepModifierFunctions.$set = function (obj, field, value) { obj[field] = value; }; -// Push an element to the end of an array field + +/** + * Push an element to the end of an array field + */ lastStepModifierFunctions.$push = function (obj, field, value) { // Create the array if it doesn't exist if (!obj.hasOwnProperty(field)) { obj[field] = []; } @@ -237,9 +242,12 @@ lastStepModifierFunctions.$push = function (obj, field, value) { obj[field].push(value); }; -// Add an element to an array field only if it is not already in it -// No modification if the element is already in the array -// Note that it doesn't check whether the original array contains duplicates + +/** + * Add an element to an array field only if it is not already in it + * No modification if the element is already in the array + * Note that it doesn't check whether the original array contains duplicates + */ lastStepModifierFunctions.$addToSet = function (obj, field, value) { // Create the array if it doesn't exist if (!obj.hasOwnProperty(field)) { obj[field] = []; } @@ -248,7 +256,26 @@ lastStepModifierFunctions.$addToSet = function (obj, field, value) { if (obj[field].indexOf(value) === -1) { obj[field].push(value); } }; -// Increment a numeric field's value + +/** + * Remove the first or last element of an array + */ +lastStepModifierFunctions.$pop = function (obj, field, value) { + if (!util.isArray(obj[field])) { throw "Can't $pop an element from non-array values"; } + if (typeof value !== 'number') { throw value + " isn't an integer, can't use it with $pop"; } + if (value === 0) { return; } + + if (value > 0) { + obj[field] = obj[field].slice(0, obj[field].length - 1); + } else { + obj[field] = obj[field].slice(1); + } +}; + + +/** + * Increment a numeric field's value + */ lastStepModifierFunctions.$inc = function (obj, field, value) { if (typeof value !== 'number') { throw value + " must be a number"; } diff --git a/test/model.test.js b/test/model.test.js index dd2b0f7..93b3083 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -411,6 +411,49 @@ describe('Model', function () { }); // End of '$addToSet modifier' + describe('$pop modifier', function () { + + it('Throw if called on a non array, a non defined field or a non integer', function () { + var obj = { arr: 'hello' } + , modified; + + (function () { + modified = model.modify(obj, { $pop: { arr: 1 } }); + }).should.throw(); + + obj = { bloup: 'nope' }; + (function () { + modified = model.modify(obj, { $pop: { arr: 1 } }); + }).should.throw(); + + obj = { arr: [1, 4, 8] }; + (function () { + modified = model.modify(obj, { $pop: { arr: true } }); + }).should.throw(); + }); + + it('Can remove the first and last element of an array', function () { + var obj + , modified; + + obj = { arr: [1, 4, 8] }; + modified = model.modify(obj, { $pop: { arr: 1 } }); + assert.deepEqual(modified, { arr: [1, 4] }); + + obj = { arr: [1, 4, 8] }; + modified = model.modify(obj, { $pop: { arr: -1 } }); + assert.deepEqual(modified, { arr: [4, 8] }); + + // Empty arrays are not changed + obj = { arr: [] }; + modified = model.modify(obj, { $pop: { arr: 1 } }); + assert.deepEqual(modified, { arr: [] }); + modified = model.modify(obj, { $pop: { arr: -1 } }); + assert.deepEqual(modified, { arr: [] }); + }); + + }); // End of '$pop modifier' + }); // ==== End of 'Modifying documents' ==== //