Can use with

pull/2/head
Louis Chatriot 9 years ago
parent 9289c79f1a
commit 1e65f366f6
  1. 26
      lib/model.js
  2. 14
      test/model.test.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,32 +274,33 @@ 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) {
if (value.$slice === undefined || typeof value.$slice !== 'number') { return; }
if (value.$slice === 0) {
obj[field] = [];
} else {
var start, end, n = obj[field].length;
if (slice < 0) {
start = Math.max(0, n + slice);
if (value.$slice < 0) {
start = Math.max(0, n + value.$slice);
end = n;
} else if (slice > 0) {
} else if (value.$slice > 0) {
start = 0;
end = Math.min(n, slice);
end = Math.min(n, value.$slice);
}
obj[field] = obj[field].slice(start, end);
}
}
} else {
obj[field].push(value);
}

@ -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'

Loading…
Cancel
Save