Better modifiers implementation

pull/2/head
Louis Chatriot 12 years ago
parent ceb4b4d15f
commit 2cf13b055d
  1. 1
      lib/datastore.js
  2. 18
      lib/model.js
  3. 50
      test/db.test.js

@ -282,5 +282,4 @@ Datastore.prototype.remove = function (query, options, cb) {
};
module.exports = Datastore;

@ -133,13 +133,13 @@ function deepCopy (obj) {
* @param {Model} value
*/
modifierFunctions.$set = function (obj, field, value) {
var fieldParts = field.split('.');
var fieldParts = typeof field === 'string' ? field.split('.') : field;
if (fieldParts.length === 1) {
obj[field] = value;
obj[fieldParts[0]] = value;
} else {
obj[fieldParts[0]] = obj[fieldParts[0]] || {};
modifierFunctions.$set(obj[fieldParts[0]], fieldParts.slice(1).join('.'), value);
modifierFunctions.$set(obj[fieldParts[0]], fieldParts.slice(1), value);
}
};
@ -152,23 +152,23 @@ modifierFunctions.$set = function (obj, field, value) {
* @param {Model} value
*/
modifierFunctions.$inc = function (obj, field, value) {
var fieldParts = field.split('.');
var fieldParts = typeof field === 'string' ? field.split('.') : field;
if (typeof value !== 'number') { throw value + " must be a number"; }
if (fieldParts.length === 1) {
if (typeof obj[field] !== 'number') {
if (!_.has(obj, field)) {
obj[field] = value;
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";
}
} else {
obj[field] += value;
obj[fieldParts[0]] += value;
}
} else {
obj[fieldParts[0]] = obj[fieldParts[0]] || {};
modifierFunctions.$inc(obj[fieldParts[0]], fieldParts.slice(1).join('.'), value);
modifierFunctions.$inc(obj[fieldParts[0]], fieldParts.slice(1), value);
}
};

@ -484,6 +484,28 @@ describe('Database', function () {
});
});
it('When using modifiers, the only way to update subdocs is with the dot-notation', function (done) {
d.insert({ bloup: { blip: "blap", other: true } }, function () {
// Correct methos
d.update({}, { $set: { "bloup.blip": "hello" } }, {}, function () {
d.findOne({}, function (err, doc) {
doc.bloup.blip.should.equal("hello");
doc.bloup.other.should.equal(true);
// Wrong
d.update({}, { $set: { bloup: { blip: "ola" } } }, {}, function () {
d.findOne({}, function (err, doc) {
doc.bloup.blip.should.equal("ola");
assert.isUndefined(doc.bloup.other); // This information was lost
done();
});
});
});
});
});
});
}); // ==== End of 'Update' ==== //
@ -534,9 +556,33 @@ describe('Database', function () {
], done);
});
}); // ==== End of 'Remove' ==== //
// This tests concurrency issues
// Right now, it doesn't pass, because I need to
//it.only('Remove can be called multiple times in parallel and everything that needs to be removed will be', function (done) {
//d.insert({ planet: 'Earth' }, function () {
//d.insert({ planet: 'Mars' }, function () {
//d.insert({ planet: 'Saturn' }, function () {
//d.find({}, function (err, docs) {
//docs.length.should.equal(3);
//// Remove two docs simultaneously
//var toRemove = ['Mars', 'Saturn'];
//async.each(toRemove, function(planet, cb) {
//d.remove({ planet: planet }, function (err) { return cb(err); });
//}, function (err) {
//d.find({}, function (err, docs) {
//docs.length.should.equal(1);
//done();
//});
//});
//});
//});
//});
//});
//});
}); // ==== End of 'Remove' ==== //
});

Loading…
Cancel
Save