From 1e65f366f605f10db014dd05f324d606cf7ba6d0 Mon Sep 17 00:00:00 2001 From: Louis Chatriot Date: Tue, 26 Jan 2016 10:22:37 +0100 Subject: [PATCH] Can use with --- lib/model.js | 38 +++++++++++++++++++++----------------- test/model.test.js | 16 ++++++++++++++-- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/lib/model.js b/lib/model.js index 54de2c9..89aec96 100755 --- a/lib/model.js +++ b/lib/model.js @@ -264,6 +264,9 @@ lastStepModifierFunctions.$unset = function (obj, field, value) { /** * Push an element to the end of an array field + * Optional modifier $each instead of value to push several values + * Optional modifier $slice to slice the resulting array, see https://docs.mongodb.org/manual/reference/operator/update/slice/ + * Différeence with MongoDB: if $slice is specified and not $each, we act as if value is an empty array */ lastStepModifierFunctions.$push = function (obj, field, value) { // Create the array if it doesn't exist @@ -271,31 +274,32 @@ lastStepModifierFunctions.$push = function (obj, field, value) { if (!util.isArray(obj[field])) { throw new Error("Can't $push an element on non-array values"); } + if (value !== null && typeof value === 'object' && value.$slice && value.$each === undefined) { + value.$each = []; + } + if (value !== null && typeof value === 'object' && value.$each) { - var keys = Object.keys(value); - if (keys.length > 1 && keys.sort()[1] !== '$slice') { - throw new Error("Can't use another field in conjunction with $each"); } + if (Object.keys(value).length >= 3 || (Object.keys(value).length === 2 && value.$slice === undefined)) { throw new Error("Can only use $slice in cunjunction with $each when $push to array"); } if (!util.isArray(value.$each)) { throw new Error("$each requires an array value"); } value.$each.forEach(function (v) { obj[field].push(v); }); - var slice = parseInt(value.$slice, 10); - if (!isNaN(slice)) { - if (slice === 0) { - obj[field] = []; - } else { - var start, end, n = obj[field].length; - if (slice < 0) { - start = Math.max(0, n + slice); - end = n; - } else if (slice > 0) { - start = 0; - end = Math.min(n, slice); - } - obj[field] = obj[field].slice(start, end); + if (value.$slice === undefined || typeof value.$slice !== 'number') { return; } + + if (value.$slice === 0) { + obj[field] = []; + } else { + var start, end, n = obj[field].length; + if (value.$slice < 0) { + start = Math.max(0, n + value.$slice); + end = n; + } else if (value.$slice > 0) { + start = 0; + end = Math.min(n, value.$slice); } + obj[field] = obj[field].slice(start, end); } } else { obj[field].push(value); diff --git a/test/model.test.js b/test/model.test.js index a91ef03..8990276 100755 --- a/test/model.test.js +++ b/test/model.test.js @@ -208,7 +208,7 @@ describe('Model', function () { model.checkObject(obj); }); - + it('Can check if an object is a primitive or not', function () { model.isPrimitiveType(5).should.equal(true); model.isPrimitiveType('sdsfdfs').should.equal(true); @@ -520,7 +520,7 @@ describe('Model', function () { }).should.throw(); }); - it('Can use the $slice modifier to limits the number of array elements', function () { + it('Can use the $slice modifier to limit the number of array elements', function () { var obj = { arr: ['hello'] } , modified; @@ -547,6 +547,18 @@ describe('Model', function () { modified = model.modify(obj, { $push: { arr: { $each: [], $slice: 1 } } }); assert.deepEqual(modified, { arr: ['hello'] }); + + // $each not specified, but $slice is + modified = model.modify(obj, { $push: { arr: { $slice: 1 } } }); + assert.deepEqual(modified, { arr: ['hello'] }); + + (function () { + modified = model.modify(obj, { $push: { arr: { $slice: 1, unauthorized: true } } }); + }).should.throw(); + + (function () { + modified = model.modify(obj, { $push: { arr: { $each: [], unauthorized: true } } }); + }).should.throw(); }); }); // End of '$push modifier'