Skip to content

Commit

Permalink
Can use with
Browse files Browse the repository at this point in the history
  • Loading branch information
louischatriot committed Jan 26, 2016
1 parent 9289c79 commit 1e65f36
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 19 deletions.
38 changes: 21 additions & 17 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,38 +264,42 @@ 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
if (!obj.hasOwnProperty(field)) { obj[field] = []; }

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);
Expand Down
16 changes: 14 additions & 2 deletions test/model.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand All @@ -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'
Expand Down

0 comments on commit 1e65f36

Please sign in to comment.