Factorization of the modifiers

pull/2/head
Louis Chatriot 12 years ago
parent 671539a614
commit d5b990e776
  1. 106
      lib/model.js
  2. 2
      test/model.test.js

@ -214,91 +214,63 @@ function compareThings (a, b) {
// Updating documents
// ==============================================================
lastStepModifierFunctions.$set = function (obj, field, value) {
obj[field] = value;
};
function findLastModificationStep (modifier, obj, field, value) {
var fieldParts = typeof field === 'string' ? field.split('.') : field;
if (fieldParts.length === 1) {
lastStepModifierFunctions[modifier](obj, field, value);
} else {
obj[fieldParts[0]] = obj[fieldParts[0]] || {};
modifierFunctions[modifier](obj[fieldParts[0]], fieldParts.slice(1), value);
}
}
/**
* Set field to value in a model
* Create it if it doesn't exist
* @param {Object} obj The model to set a field for
* The signature of modifier functions is as follows
* Their structure is always the same: recursively follow the dot notation while creating
* the nested documents if needed, then apply the "last step modifier"
* @param {Object} obj The model to modify
* @param {String} field Can contain dots, in that case that means we will set a subfield recursively
* @param {Model} value
*/
modifierFunctions.$set = function (obj, field, value) {
var fieldParts = typeof field === 'string' ? field.split('.') : field;
if (fieldParts.length === 1) {
obj[fieldParts[0]] = value;
} else {
obj[fieldParts[0]] = obj[fieldParts[0]] || {};
modifierFunctions.$set(obj[fieldParts[0]], fieldParts.slice(1), 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
lastStepModifierFunctions.$push = function (obj, field, value) {
// Create the array if it doesn't exist
if (!obj.hasOwnProperty(field)) { obj[field] = []; }
/**
* Push an element at the last place of an array
* @param {Object} obj The model to set a field for
* @param {String} field Can contain dots, in that case that means we will set a subfield recursively
* @param {Model} value
*/
modifierFunctions.$push = function (obj, field, value) {
var fieldParts = typeof field === 'string' ? field.split('.') : field;
if (fieldParts.length === 1) {
// Create the array if it doesn't exist
if (!obj.hasOwnProperty(fieldParts[0])) { obj[fieldParts[0]] = []; }
if (!util.isArray(obj[fieldParts[0]])) { throw "Can't $push an element on non-array values"; }
obj[fieldParts[0]].push(value);
} else {
obj[fieldParts[0]] = obj[fieldParts[0]] || {};
modifierFunctions.$push(obj[fieldParts[0]], fieldParts.slice(1), value);
}
if (!util.isArray(obj[field])) { throw "Can't $push an element on non-array values"; }
obj[field].push(value);
};
/**
* Increase (or decrease) a 'number' field
* Create and initialize it if needed
* @param {Object} obj The model to set a field for
* @param {String} field Can contain dots, in that case that means we will set a subfield recursively
* @param {Model} value
*/
modifierFunctions.$inc = function (obj, field, value) {
var fieldParts = typeof field === 'string' ? field.split('.') : field;
// Increment a numeric field's value
lastStepModifierFunctions.$inc = function (obj, field, value) {
if (typeof value !== 'number') { throw value + " must be a number"; }
if (fieldParts.length === 1) {
if (typeof obj[fieldParts[0]] !== 'number') {
if (!_.has(obj, fieldParts[0])) {
obj[fieldParts[0]] = value;
} else {
throw "Don't use the $inc modifier on non-number fields";
}
if (typeof obj[field] !== 'number') {
if (!_.has(obj, field)) {
obj[field] = value;
} else {
obj[fieldParts[0]] += value;
throw "Don't use the $inc modifier on non-number fields";
}
} else {
obj[fieldParts[0]] = obj[fieldParts[0]] || {};
modifierFunctions.$inc(obj[fieldParts[0]], fieldParts.slice(1), value);
obj[field] += value;
}
};
// Given its name, create the complete modifier function
function createModifierFunction (modifier) {
return function (obj, field, value) {
var fieldParts = typeof field === 'string' ? field.split('.') : field;
if (fieldParts.length === 1) {
lastStepModifierFunctions[modifier](obj, field, value);
} else {
obj[fieldParts[0]] = obj[fieldParts[0]] || {};
modifierFunctions[modifier](obj[fieldParts[0]], fieldParts.slice(1), value);
}
};
}
// Actually create all modifier functions
Object.keys(lastStepModifierFunctions).forEach(function (modifier) {
modifierFunctions[modifier] = createModifierFunction(modifier);
});
/**
* Modify a DB object according to an update query

@ -201,7 +201,7 @@ describe('Model', function () {
}); // ==== End of 'Deep copying' ==== //
describe.only('Modifying documents', function () {
describe('Modifying documents', function () {
it('Queries not containing any modifier just replace the document by the contents of the query but keep its _id', function () {
var obj = { some: 'thing', _id: 'keepit' }

Loading…
Cancel
Save