Skip to content

Commit

Permalink
Added additional hooks, and a better hooking system
Browse files Browse the repository at this point in the history
  • Loading branch information
notheotherben committed Dec 23, 2013
1 parent 3891b2b commit e3d694e
Show file tree
Hide file tree
Showing 4 changed files with 322 additions and 60 deletions.
88 changes: 44 additions & 44 deletions lib/Instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,23 +125,25 @@ function Instance(model, doc, isNew) {
if (!cb) cb = function () { };

var createObject = function (callback) {

var createDoc = _.cloneDeep(newDoc);
model.toSource(createDoc);

model.collection.insert(createDoc, { w: 1 }, function (err, inserted) {
model.onCreating(createDoc, function(err) {
if (err) return callback(err);

inserted = inserted[0];
model.fromSource(inserted);

oldDoc = newDoc = inserted;

addSchemaProperties();

isNew = false;

return callback(null, $);
model.toSource(createDoc);

model.collection.insert(createDoc, { w: 1 }, function (err, inserted) {
if (err) return callback(err);

isNew = false;
return model.onRetrieved(inserted[0], callback, function(value) {
model.fromSource(value);
oldDoc = _.cloneDeep(value);
newDoc = _.cloneDeep(value);
addSchemaProperties();
return $;
});
});
});
};

Expand All @@ -160,32 +162,31 @@ function Instance(model, doc, isNew) {

var conditions = model.uniqueConditions(newDoc);

model.collection.update(conditions, changes, { w: 1 }, function (err, updateCount) {
if (err) return cb(err);

if (updateCount > 0) {
model.collection.findOne(conditions, function (err, updated) {
if (err) return cb(err);

model.fromSource(updated);

newDoc = _.cloneDeep(updated);
oldDoc = _.cloneDeep(updated);

addSchemaProperties();

return cb(null, $);
});
} else return cb(null, $);
});
model.onSaving($, changes, function(err) {
if(err) return cb(err);

model.collection.update(conditions, changes, { w: 1 }, function (err, updateCount) {
if (err) return cb(err);

if (updateCount > 0) {
model.collection.findOne(conditions, function (err, updated) {
if (err) return cb(err);

return model.onRetrieved(updated, cb, function(value) {
model.fromSource(value);
oldDoc = _.cloneDeep(value);
newDoc = _.cloneDeep(value);
addSchemaProperties();
return $;
});
});
} else return cb(null, $);
});
});
};

if (!isNew) return runOptions();
else createObject(function (err) {
if (err) return cb(err);
if (Object.keys(changes).length > 0) runOptions(cb);
else return cb(null, $);
});
else createObject(cb);
}
else return cb(null, $);
},
Expand All @@ -206,14 +207,13 @@ function Instance(model, doc, isNew) {

model.collection.findOne(conditions, function (err, updated) {
if (err) return cb(err);

model.fromSource(updated);

oldDoc = newDoc = updated;

addSchemaProperties();

if(callback) return callback(null, $);
return model.onRetrieved(updated,callback, function(value) {
model.fromSource(value);
oldDoc = _.cloneDeep(value);
newDoc = _.cloneDeep(value);
addSchemaProperties();
return $;
});
});
}
});
Expand Down
154 changes: 139 additions & 15 deletions lib/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Model.prototype.downstreamID = function(id) {
/// </signature>
/// <signature>
/// <summary>Gets the set of conditions representing the downstream _id field for the given downstream identifier</summary>
/// <param name="id" type="Mixed">The identifier to created the conditions from</param>
/// <param name="id" type="Mixed">The identifier to create the conditions from</param>
/// <returns type="Object"/>
/// </signature>

Expand Down Expand Up @@ -161,6 +161,140 @@ Model.prototype.wrap = function (document, isNew) {
return new Instance(this, document, isNew);
};

Model.prototype.onRetrieved = function(results, callback, wrapper) {
///<signature>
///<summary>Handles any post-receive hooks and the wrapping of objects from the database</summary>
///<param name="results" type="Object">The object retrieved from the database</param>
///<param name="callback" type="Function">The function to be called once the objects have been wrapped</param>
///</signature>
///<signature>
///<summary>Handles any post-receive hooks and the wrapping of objects from the database</summary>
///<param name="results" type="Array" elementType="Object">The objects retrieved from the database</param>
///<param name="callback" type="Function">The function to be called once the objects have been wrapped</param>
///</signature>
///<signature>
///<summary>Handles any post-receive hooks and the wrapping of objects from the database</summary>
///<param name="results" type="Object">The object retrieved from the database</param>
///<param name="callback" type="Function">The function to be called once the objects have been wrapped</param>
///<param name="wrapper" type="Function">A function which converts the retrieved objects prior to submission</param>
///</signature>
///<signature>
///<summary>Handles any post-receive hooks and the wrapping of objects from the database</summary>
///<param name="results" type="Array" elementType="Object">The objects retrieved from the database</param>
///<param name="callback" type="Function">The function to be called once the objects have been wrapped</param>
///<param name="wrapper" type="Function">A function which converts the retrieved objects prior to submission</param>
///</signature>

var $ = this;
wrapper = wrapper || this.wrap.bind(this);

var toProcess = results;

var output = [];
var errors = [];
var remaining = 1;

if(!Array.isArray(toProcess)) toProcess = [toProcess];

function doHook(hook, target, next) {
if(!hook) return next();
if(hook.length === 0) {
try {
hook.call(target);
return next();
} catch(err) {
return next(err);
}
} else {
hook.call(target, next);
}
}

function onComplete() {
remaining--;
if(remaining === 0) {
if(Array.isArray(results)) {
for(var i = 0; i < errors.length; i++)
if(errors[i]) return callback(errors[i]);
return callback(null, output);
} else {
return callback(errors[0], output[0]);
}
}
}

function process(target) {
doHook($.options.hooks.retrieved, target, function(err) {
if(err) {
errors.push(err);
output.push(null);
return onComplete();
}

var wrapped = wrapper(target);

doHook($.options.hooks.ready, wrapped, function(err) {
if(err) {
errors.push(err);
output.push(null);
return onComplete();
}

errors.push(null);
output.push(wrapped);
return onComplete();
});
});
}
for(var i = 0; i < toProcess.length; i++) {
remaining++;
process(toProcess[i]);
}

return onComplete();
};

Model.prototype.onCreating = function(document, callback) {
function doHook(hook, target, args, next) {
if(!hook) return next();
if(hook.length === 0) {
try {
hook.apply(target, args);
return next();
} catch(err) {
return next(err);
}
} else {
args.push(next);
hook.apply(target, args);
}
}

doHook(this.options.hooks.creating || this.options.hooks.beforeCreate, document, [], callback);
};

Model.prototype.onSaving = function(instance, changes, callback) {

function doHook(hook, target, args, next) {
if(!hook) return next();
if(hook.length === 0) {
try {
hook.apply(target, args);
return next();
} catch(err) {
return next(err);
}
} else {
args.push(next);
hook.apply(target, args);
}
}

var $ = this;

doHook($.options.hooks.saving, instance, [changes], callback);
};

Model.prototype.find = function (conditions, callback) {
/// <signature>
/// <summary>Gets all objects in the collection.</summary>
Expand Down Expand Up @@ -189,7 +323,7 @@ Model.prototype.find = function (conditions, callback) {
this.collection.find(conditions).toArray(function (err, results) {
if (err) return callback(err);
if (!results) return callback(null, null);
return callback(null, _.map(results, function (result) { return $.wrap(result, false); }, $));
return $.onRetrieved(results, callback);
});
};

Expand Down Expand Up @@ -223,7 +357,7 @@ Model.prototype.findOne = Model.prototype.get = function (conditions, callback)
if (err) return callback(err);
if (!results) return callback(null, null);

return callback(null, $.wrap.call($, results));
return $.onRetrieved(results, callback);
});
};

Expand Down Expand Up @@ -256,7 +390,6 @@ Model.prototype.insert = Model.prototype.create = function (object, callback) {
returnArray = false;
}


var prepped = [];

var end = function(err, results) {
Expand All @@ -273,7 +406,7 @@ Model.prototype.insert = Model.prototype.create = function (object, callback) {
var prepComplete = function() {
$.collection.insert(prepped, { w: callback ? 1 : 0 }, function(err, inserted) {
if(err) return end(err);
return end(null, inserted.map(function(item) { return $.wrap(item, false); }));
return $.onRetrieved(inserted, end);
});
};

Expand All @@ -297,16 +430,7 @@ Model.prototype.insert = Model.prototype.create = function (object, callback) {
return prepNext();
}

// Run the beforeCreate hook
if($.options.hooks.beforeCreate) {
if($.options.hooks.beforeCreate.length > 0) return $.options.hooks.beforeCreate.call(obj, postHook);
else try {
$.options.hooks.beforeCreate.call(obj);
postHook();
} catch(ex) {
postHook(ex);
}
} else postHook();
$.onCreating(obj, postHook);
};

prepNext();
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iridium",
"version": "2.4.3",
"version": "2.5.0",
"author": "Benjamin Pannell <admin@sierrasoftworks.com>",
"description": "A custom lightweight ORM for MongoDB designed for power-users",
"homepage": "https://sierrasoftworks.com/iridium",
Expand Down
Loading

0 comments on commit e3d694e

Please sign in to comment.