Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor link and unlink to be simpler (removed directChange, added e…

…rror callback)

Changes save() to receive an options object (silent and continue_on_link_error so far)
  • Loading branch information...
commit b3f29fb2e3755b9d7f59472d326589baecf1ad1e 1 parent 8898af5
@maritz authored
View
4 lib/helpers.js
@@ -170,14 +170,14 @@ Helper.getCallback = function getCallback(args) {
};
/**
- * Checks whether 2 nohm objects are the same.
+ * Checks whether 2 (nohm) objects are the same.
*/
Helper.checkEqual = function checkEqual(obj1, obj2) {
if (!obj1 || (obj1 && !obj2)) {
return false;
}
if (obj1 === obj2) {
- return true; // hm... is this ever going to trigger? i don't know
+ return true;
}
else if (obj1.hasOwnProperty('modelName') && obj2.hasOwnProperty('modelName') &&
obj1.modelName === obj2.modelName) {
View
1  lib/nohm.js
@@ -197,7 +197,6 @@ var addMethods = function (methods) {
this[name] = methods[name].bind(this);
}
}
-
};
Nohm.prototype.init = function (name, options) {
View
227 lib/relations.js
@@ -3,8 +3,8 @@ exports.setNohm = function (originalNohm) {
Nohm = originalNohm;
};
-var async = require('async'),
- h = require(__dirname + '/helpers');
+var async = require('async');
+var h = require(__dirname + '/helpers');
/**
* Check if the object has a relation to another object.
@@ -12,7 +12,7 @@ var async = require('async'),
exports.belongsTo = function belongsTo(obj, name) {
var callback = h.getCallback(arguments),
self = this;
- name = name && typeof name !== 'function' ? name : 'child';
+ name = name && typeof name !== 'function' ? name : 'default';
if (!this.id || !obj.id) {
Nohm.logError('Calling belongsTo() even though either the object itself or the relation does not have an id.');
}
@@ -40,7 +40,7 @@ exports.relationKey = function relationKey(objName, name) {
exports.getAll = function getAll(objName, name) {
var callback = h.getCallback(arguments),
self = this;
- name = name && typeof name !== 'function' ? name : 'child';
+ name = name && typeof name !== 'function' ? name : 'default';
if (!this.id) {
Nohm.logError('Calling getAll() even though this '+this.modelName+' has no id. Please load or save it first.');
}
@@ -50,7 +50,6 @@ exports.getAll = function getAll(objName, name) {
self.logError(err);
}
if (!Array.isArray(value)) {
- console.log('getAll has got a non-array value');
value = [];
} else {
value = value.map(function (val) {
@@ -68,13 +67,13 @@ exports.getAll = function getAll(objName, name) {
* Returns the number of links of a specified relation (or the default) an instance has to models of a given modelName.
*
* @param {String} obj_name Name of the model on the other end of the relation.
- * @param {String} [relation_name="child"] Name of the relation
- * @param {Function} Callback Callback called with (err, num_relations
+ * @param {String} [relation_name="default"] Name of the relation
+ * @param {Function} callback Callback called with (err, num_relations
*/
exports.numLinks = function numLinks(obj_name, relation_name, callback) {
callback = h.getCallback(arguments);
var self = this;
- relation_name = relation_name && typeof relation_name !== 'function' ? relation_name : 'child';
+ relation_name = relation_name && typeof relation_name !== 'function' ? relation_name : 'default';
if (!this.id) {
Nohm.logError('Calling numLinks() even though either the object itself or the relation does not have an id.');
}
@@ -89,92 +88,94 @@ exports.numLinks = function numLinks(obj_name, relation_name, callback) {
var allowedLinkTypes = ['sadd', 'srem'];
-exports.__linkProxied = function __linkProxied(type, obj, name, options, callback) {
+exports.__linkProxied = function __linkProxied(type, obj, options, callback) {
+
options = typeof(options) === 'object' && Object.keys(options).length > 0 ? options : {};
callback = h.getCallback(arguments);
var self = this,
- parentName = name === 'child' ? 'parent' : name + 'Parent',
+ foreignName = options.name + 'Foreign',
silent = !!options.silent,
client = self.getClient(),
- redisExec = function (err, childFail, childName) {
- if (!err || typeof err === 'function') {
- var dbVals = [{
- key: self.relationKey(obj.modelName, name),
- keyStore: self.modelName+':'+self.id,
- id: obj.id
- }, {
- key: obj.relationKey(self.modelName, parentName),
- keyStore: obj.modelName+':'+obj.id,
- id: self.id
+ redisExec = function (cb) {
+ var dbVals = [{
+ key: self.relationKey(obj.modelName, options.name),
+ keyStore: self.modelName+':'+self.id,
+ id: obj.id
+ }, {
+ key: obj.relationKey(self.modelName, foreignName),
+ keyStore: obj.modelName+':'+obj.id,
+ id: self.id
+ }
+ ];
+
+ async.forEach(dbVals,
+ function (val, next) {
+ var multi = client.multi();
+ multi[type](Nohm.prefix.relationKeys+val.keyStore, val.key);
+ multi[type](val.key, val.id);
+ multi.exec(next);
+ },
+ function (err) {
+ if (!silent && !err) {
+ self.fireEvent( type === 'sadd' ? 'link' : 'unlink', obj, options.name );
}
- ];
- async.forEach(dbVals,
- function (val, next) {
- client[type](Nohm.prefix.relationKeys+val.keyStore, val.key);
- client[type](val.key, val.id, next);
- },
- function (err) {
-
- if (!silent && !err) {
- self.fireEvent( type === 'sadd' ? 'link' : 'unlink', obj, name );
- }
-
- callback.call(self, err);
+ if (err && typeof(options.error) === 'function') {
+ options.error(err, 'Linking failed.', obj);
}
- );
- } else if (err && childFail) {
- callback.call(self, err, childFail, childName);
- } else {
- callback.call(self, err);
- }
+ cb.call(self, err);
+ }
+ );
};
-
+
if (allowedLinkTypes.indexOf(type) === -1) {
callback.call(self, 'wrong link/unlink type invocation');
} else if (!this.id) {
- callback.call(self, 'save parent object before adding a child.');
+ callback.call(self, 'You need to save an object before adding a link. (this might be a nohm error)');
} else if (!obj.id) {
- obj.save(options, redisExec);
+ obj.save(options, function (err, link_error, link_name) {
+ if (err && !link_error && typeof(options.error) === 'function') {
+ options.error(err, obj.errors, obj);
+ }
+ if (err) {
+ callback(err, link_error, link_name);
+ } else {
+ redisExec(callback);
+ }
+ });
} else {
- redisExec();
+ redisExec(callback);
}
};
-exports.__link = function __link(obj, name, options, cb) {
- this.__linkProxied('sadd', obj, name, options, cb);
+exports.__link = function __link(obj, options, cb) {
+ this.__linkProxied('sadd', obj, options, cb);
};
-exports.__unlink = function __unlink(obj, name, options, cb) {
- this.__linkProxied('srem', obj, name, options, cb);
+exports.__unlink = function __unlink(obj, options, cb) {
+ this.__linkProxied('srem', obj, options, cb);
};
/**
* Adds a reference to another object.
*/
-exports.link = function link(obj, name, directChange) {
-
- // TODO
- var options = {};
-
- var callback = h.getCallback(arguments);
- name = name && typeof name !== 'function' ? name : 'child';
- directChange = typeof directChange !== 'function' ? !!directChange : false;
-
- if (this.id && directChange && obj.valid()) {
-
- this.__link(obj, name, options, callback);
-
- } else {
-
- this.relationChanges.push({
- action: 'link',
- object: obj,
- name: name,
- callback: callback
- });
+exports.link = function link(obj, options, callback) {
+ if (typeof(options) === 'string') {
+ options = {name: options};
}
+ var opts = h.$extend({
+ name: 'default'
+ }, options);
+
+ callback = h.getCallback(arguments);
+
+ this.relationChanges.push({
+ action: 'link',
+ object: obj,
+ options: opts,
+ callback: callback
+ });
};
/**
@@ -182,47 +183,29 @@ exports.link = function link(obj, name, directChange) {
* the object given in the first argument.
* Note: this leaves the given object itself intact.
*/
-exports.unlink = function unlink(obj, name, directChange) {
-
- // TODO
- var options = {};
-
- var callback = h.getCallback(arguments),
- changes = this.relationChanges;
-
- name = name && typeof name !== 'function' ? name : 'child';
- directChange = typeof directChange !== 'function' ? !!directChange : false;
+exports.unlink = function unlink(obj, options, callback) {
- if (this.id && directChange && obj.id) {
+ var opts = h.$extend({
+ name: 'default'
+ }, options);
- this.__unlink(obj, name, options, callback);
-
- } else if (!this.id) {
-
- /* the object hasn't been added to the db yet.
- * this means it's still in the relationchanges array
- * and we can just take it out there.
- * (or it was never added, in which case nothing happens here.)
- */
- for (var i in changes) {
- if (changes.hasOwnProperty(i) &&
- changes[i].action === 'add' &&
- changes[i].name === name &&
- checkEqual(changes[i].object, obj)) {
- delete this.relationChanges[i];
- }
+ callback = h.getCallback(arguments);
+
+ var changes = this.relationChanges;
+ for (var i in changes) {
+ if (changes.hasOwnProperty(i) &&
+ changes[i].name === opts.name &&
+ h.checkEqual(changes[i].object, obj)) {
+ delete this.relationChanges[i];
}
-
- } else {
-
- this.relationChanges.push({
- action: 'unlink',
- name: name,
- callback: callback,
- object: obj
- });
-
}
+
+ this.relationChanges.push({
+ action: 'unlink',
+ options: opts,
+ callback: callback,
+ object: obj
+ });
};
/**
@@ -231,9 +214,11 @@ exports.unlink = function unlink(obj, name, directChange) {
exports.unlinkAll = function (client, callback) {
var self = this;
var normalClient = this.getClient();
- var selfLinks = [];
+ var links = [];
client = client || normalClient;
+ this.relationChanges = [];
+
// we usenormalClient for fetching data and client (which could be a provided client in multi mode) for manipulating data
normalClient.smembers(Nohm.prefix.relationKeys+this.modelName+':'+this.id, function (err, keys) {
var others = [];
@@ -242,18 +227,18 @@ exports.unlinkAll = function (client, callback) {
var selfName = matches[1];
var otherName;
var namedMatches;
- if (matches[1] === 'child') {
- otherName = 'parent';
- } else if (matches[1] === 'parent') {
- otherName = 'child';
+ if (matches[1] === 'default') {
+ otherName = 'defaultForeign';
+ } else if (matches[1] === 'defaultForeign') {
+ otherName = 'default';
} else {
- namedMatches = matches[1].match(/^([\w]*)Parent$/);
+ namedMatches = matches[1].match(/^([\w]*)Foreign$/);
if (namedMatches) {
- selfName = matches[1]+'Parent';
+ selfName = matches[1];
otherName = namedMatches[1];
} else {
selfName = matches[1];
- otherName = matches[1] + 'Parent';
+ otherName = matches[1] + 'Foreign';
}
}
others.push({
@@ -262,7 +247,7 @@ exports.unlinkAll = function (client, callback) {
otherName: otherName
});
});
- async.forEach(others, function (item, cb) {
+ async.map(others, function (item, cb) {
normalClient.smembers(
Nohm.prefix.relations+self.modelName+':'+item.selfName+':'+item.model+':'+self.id,
function (err, ids) {
@@ -272,13 +257,17 @@ exports.unlinkAll = function (client, callback) {
ids.forEach(function (id) {
client.srem(Nohm.prefix.relations+item.model+':'+item.otherName+':'+self.modelName+':'+id, self.id);
});
- selfLinks.push(Nohm.prefix.relations+self.modelName+':'+item.selfName+':'+item.model+':'+self.id);
- cb(err);
+ cb(err, Nohm.prefix.relations+self.modelName+':'+item.selfName+':'+item.model+':'+self.id);
}
);
- }, function (err) {
- if (selfLinks.length > 0) {
- client.del.apply(client, selfLinks);
+ }, function (err, links) {
+ if (links.length > 0) {
+ links.push(function (err) {
+ if (err) {
+ Nohm.logError('There was a problem while deleting keys:'+err);
+ }
+ });
+ client.del.apply(client, links);
}
callback.call(self, err);
});
View
49 lib/store.js
@@ -14,16 +14,18 @@ var noop = function () {};
exports.save = function save(options) {
var callback = h.getCallback(arguments);
- options = options && typeof options !== 'function' ? options : {};
+
+ options = h.$extend({
+ silent: false,
+ continue_on_link_error: false
+ }, options);
var self = this,
id_tries = 0,
action = 'create',
- idGenerated = false,
silent = !!options.silent;
var generateId = function () {
- idGenerated = true;
// this is only a temporary id. it's negative so there's a way to identify some
// corrupted data if there's a redis failure between the first write of this
// model and the id change to its final real id
@@ -52,9 +54,9 @@ exports.save = function save(options) {
}
callback.call(self, 'invalid');
} else if (valid && action === 'create') {
- __create.call(self, silent, callback);
+ __create.call(self, options, callback);
} else if (valid) {
- __update.call(self, false, silent, callback);
+ __update.call(self, false, options, callback);
}
});
};
@@ -115,7 +117,7 @@ var __generate_id = function (cb) {
* Creates a new empty (!) dataset in the database and calls __update to populate it.
* @ignore
*/
-var __create = function __create(silent, callback) {
+var __create = function __create(options, callback) {
var self = this;
__generate_id.call(this, function (newId) {
self.getClient().sadd(Nohm.prefix.idsets + self.modelName, newId, function (err) {
@@ -123,7 +125,7 @@ var __create = function __create(silent, callback) {
self.__setUniqueIds(newId, function (err) {
if (err) { Nohm.logError(err); }
self.id = newId;
- __update.call(self, true, silent, callback);
+ __update.call(self, true, options, callback);
});
});
});
@@ -151,9 +153,12 @@ exports.__index = function __index(p, client) {
* Update an existing dataset with the new values.
* @ignore
*/
-var __update = function __update(all, silent, callback) {
+var __update = function __update(all, options, callback) {
- var options = {silent: !!silent};
+ options = h.$extend({
+ silent: false,
+ continue_on_link_error: false
+ }, options);
var p,
hmsetArgs = [],
@@ -199,29 +204,31 @@ var __update = function __update(all, silent, callback) {
// we're using a serial forEach here because otherwise multiple objects
// may error out without notifying the callback
- // this way once one fails it goes to error directly
+ // this way once one fails it goes to error directly except if options.continue_on_link_error is set to true
async.forEachSeries(self.relationChanges,
function (item, cb) {
- self['__' + item.action](item.object, item.name, options, function (err, childFail, childName) {
+ item.options.continue_on_link_error = options.continue_on_link_error
+ item.options.silent = options.silent;
+ self['__' + item.action](item.object, item.options, function (err, child_fail, child_name) {
item.callback.call(self,
item.action,
self.modelName,
- item.name,
+ item.options.name,
item.object);
- if (err && childFail) {
- cb({ err: err, modelName: childName});
- } else if (err) {
- cb({ err: err, modelName: item.object.modelName});
- } else {
+
+ if (options.continue_on_link_error || !err) {
cb();
+ } else if (child_fail) {
+ cb({ err: err, modelName: child_name});
+ } else {
+ cb({ err: err, modelName: item.object.modelName});
}
});
},
function (err) {
if (typeof callback !== 'function' && err) {
- Nohm.logError('Nohm: Updating an object resulted in a client error: ' + err);
- throw err;
+ Nohm.logError('Nohm: Updating an object resulted in an error and no callback was provided: ' + err);
} else if (err) {
@@ -229,7 +236,7 @@ var __update = function __update(all, silent, callback) {
} else {
var diff;
- if (!silent && self.getPublish()) {
+ if (!options.silent && self.getPublish()) {
// we only need the diff if we'll fire the change to pubsub
diff = self.propertyDiff();
}
@@ -241,7 +248,7 @@ var __update = function __update(all, silent, callback) {
}
}
- if (!silent) {
+ if (!options.silent) {
if (isCreation) {
self.fireEvent('create');
} else {
View
6 test/featureTests.js
@@ -713,7 +713,7 @@ exports.allPropertiesJson = function (t) {
exports.thisInCallbacks = function (t) {
var user = new UserMockup();
var checkCounter = 0;
- var checkSum = 13;
+ var checkSum = 11;
var checkThis = function (name, cb) {
return function () {
checkCounter++;
@@ -749,9 +749,7 @@ exports.thisInCallbacks = function (t) {
user.belongsTo(user, checkThis('belongsTo'));
user.getAll('UserMockup', checkThis('getAll'));
user.numLinks('UserMockup', checkThis('numLinks'));
- user.link(user, 'childa', true, checkThis('linkDirect'));
- user.unlink(user, 'childa', true, checkThis('linkDirect'));
- user.unlinkAll(null, checkThis('linkDirect'));
+ user.unlinkAll(null, checkThis('unlinkAll'));
}));
}));
};
View
178 test/relationTests.js
@@ -1,5 +1,6 @@
var nohm = require(__dirname+'/../lib/nohm').Nohm;
var args = require(__dirname+'/testArgs.js');
+var async = require('async');
var redis = args.redis;
var h = require(__dirname+'/helper.js');
var relationsprefix = nohm.prefix.relations;
@@ -24,8 +25,7 @@ var CommentLinkMockup = nohm.model('CommentLinkMockup', {
'notEmpty'
]
}
- },
- idGenerator: 'increment'
+ }
});
var RoleLinkMockup = nohm.model('RoleLinkMockup', {
properties: {
@@ -55,16 +55,16 @@ exports.relation = {
var user = new UserLinkMockup(),
role = new RoleLinkMockup(),
role2;
-
+
t.expect(2);
-
+
role.link(user);
-
+
t.ok(role.relationChanges !== user.relationChanges, 'Instances share the relationchanges, initiate them as an empty array in the constructor.');
-
+
role2 = new RoleLinkMockup();
t.same(role2.relationChanges, [], 'Creating a new instance does not reset the relationchanges of that instance.');
-
+
t.done();
},
@@ -81,13 +81,13 @@ exports.relation = {
linkCallbackCalled = true;
t.equals(action, 'link', 'The argument "action" given to the link callback are not correct');
t.equals(on, 'UserLinkMockup', 'The argument "on" given to the link callback are not correct');
- t.equals(name, 'child', 'The argument "name" given to the link callback are not correct');
+ t.equals(name, 'default', 'The argument "name" given to the link callback are not correct');
t.same(obj, role, 'The argument "obj" given to the link callback are not correct');
});
role2.p('name', 'test');
- user.link(role2, function (action, on, name, obj) {
+ user.link(role2, function () {
linkCallbackCalled2 = true;
});
@@ -139,7 +139,7 @@ exports.relation = {
unlinkCallbackCalled = true;
t.equals(action, 'unlink', 'The argument "action" given to the unlink callback are not correct');
t.equals(on, 'UserLinkMockup', 'The argument "on" given to the unlink callback are not correct');
- t.equals(name, 'child', 'The argument "name" given to the unlink callback are not correct');
+ t.equals(name, 'default', 'The argument "name" given to the unlink callback are not correct');
t.equals(obj, role, 'The argument "obj" given to the unlink callback are not correct');
});
@@ -174,10 +174,10 @@ exports.relation = {
commentLinkCallbackCalled = false;
t.expect(5);
- role.link(user, function (action, on, name, obj) {
+ role.link(user, function () {
userLinkCallbackCalled = true;
});
- user.link(comment, function (action, on, name, obj) {
+ user.link(comment, function () {
commentLinkCallbackCalled = true;
});
@@ -190,7 +190,7 @@ exports.relation = {
t.ok(commentLinkCallbackCalled, 'The comment link callback was not called.');
t.ok(user.id !== null, 'The deeplinked user does not have an id and thus is probably not saved correctly.');
t.ok(comment.id !== null, 'The deeplinked comment does not have an id and thus is probably not saved correctly.');
- redis.smembers(relationsprefix + comment.modelName + ':parent:' +
+ redis.smembers(relationsprefix + comment.modelName + ':defaultForeign:' +
user.modelName + ':' + comment.id,
function (err, value) {
if (!err) {
@@ -204,50 +204,68 @@ exports.relation = {
},
removeUnlinks: function (t) {
+ // uses unlinkAll in remove
var user = new UserLinkMockup(),
role = new RoleLinkMockup(),
role2 = new RoleLinkMockup(),
comment = new CommentLinkMockup(),
linkName = 'creator';
- t.expect(9);
+ t.expect(8);
user.p('name', 'removeUnlinks');
- user.link(role, linkName);
+ role.link(user, linkName);
+ user.link(role, 'isA');
user.link(comment);
role2.link(user);
role2.save(function (err) {
- if (err) {
- console.dir(err);
- t.done();
- }
+ t.ok(!err, 'there was an unexpected error while saving.');
var tmpid = user.id;
user.remove(function (err) {
t.ok(!err, 'An unexpected redis error occured.');
- redis.exists(relationsprefix + user.modelName + ':'+linkName+':' +
- role.modelName + ':' + tmpid, function (err, value) {
- t.ok(!err, 'An unexpected redis error occured.');
- t.equals(value, 0, 'The link to the custom-link-name role was not deleted');
- redis.exists(relationsprefix + user.modelName + ':child:' +
- comment.modelName + ':' + tmpid, function (err, value) {
- t.ok(!err, 'An unexpected redis error occured.');
+ async.parallel([
+ function (next) {
+ redis.exists(relationsprefix+user.modelName+':'+linkName+'Foreign:'+role.modelName+':'+tmpid,
+ function (err, value) {
+ t.equals(value, 0, 'The foreign link to the custom-link-name role was not deleted');
+ next(err);
+ });
+ },
+ function (next) {
+ redis.exists(relationsprefix+role.modelName+':'+linkName+':'+user.modelName+':'+role.id,
+ function (err, value) {
+ t.equals(value, 0, 'The link to the custom-link-name role was not deleted');
+ next(err);
+ });
+ },
+ function (next) {
+ redis.exists(relationsprefix+user.modelName+':default:'+comment.modelName+':'+tmpid,
+ function (err, value) {
t.equals(value, 0, 'The link to the child comment was not deleted');
- redis.sismember(relationsprefix + comment.modelName + ':parent:' +
- user.modelName + ':' + comment.id, tmpid,
- function (err, value) {
- t.ok(!err, 'An unexpected redis error occured.');
- t.equals(value, 0, 'The link to the comment parent was not deleted');
- redis.sismember(relationsprefix + role2.modelName + ':child:' +
- user.modelName + ':' + role2.id, tmpid,
- function (err, value) {
- t.ok(!err, 'An unexpected redis error occured.');
- t.equals(value, 0, 'The removal did not delete the link from a parent to the object itself.');
- t.done();
- });
- });
- });
- });
+ next(err);
+ });
+ },
+ function (next) {
+ redis.sismember(relationsprefix+comment.modelName+':defaultForeign:'+user.modelName+':'+comment.id, tmpid,
+ function (err, value) {
+ t.equals(value, 0, 'The link to the comment parent was not deleted');
+ next(err);
+ });
+ },
+ function (next) {
+ redis.sismember(relationsprefix+role2.modelName+':default:'+user.modelName+':'+role2.id, tmpid,
+ function (err, value) {
+ t.equals(value, 0, 'The removal did not delete the link from a parent to the object itself.');
+ next(err);
+ }
+ );
+ }],
+ function (err) {
+ t.ok(!err, 'An unexpected redis error occured.');
+ t.done();
+ }
+ );
});
});
},
@@ -364,6 +382,84 @@ exports.relation = {
t.ok(!err, 'Linking an object to itself failed.');
t.done();
});
+ },
+
+ deppLinkErrorCallback: function (t) {
+ var user = new UserLinkMockup(),
+ role = new RoleLinkMockup(),
+ comment = new CommentLinkMockup();
+ t.expect(8);
+
+ role.link(user, {
+ error: function (err, errors, obj) {
+ console.log(err, errors, obj.allProperties())
+ t.ok(false, 'Error callback for role.link(user) called even though user is valid.');
+ }
+ });
+ user.link(comment, {
+ error: function (err, errors, obj) {
+ t.same(err, 'invalid', 'err in error callback was not "invalid"');
+ t.same(errors, comment.errors, 'errors in error callback was not comment.errors');
+ t.same(comment, obj, 'obj in Error callback was not the right object.');
+ }
+ });
+ comment.p('text', ''); // makes the comment fail
+
+ role.save(function (err, childFail, childName) {
+ t.ok(user.id !== null, 'The deeplinked user does not have an id and thus is probably not saved correctly.');
+ t.same(comment.id, null, 'The deeplinked erroneous comment does not have an id and thus is probably saved.');
+ t.same(err, 'invalid', 'The deeplinked role did not fail.');
+ t.same(childFail, true, 'The deeplinked role did not fail in a child or reported it wrong.');
+ t.same(childName, 'CommentLinkMockup', 'The deeplinked role failed in the wrong model or reported it wrong.');
+ t.done();
+ });
+ },
+
+ contineOnError: function (t) {
+ var user = new UserLinkMockup(),
+ role = new RoleLinkMockup(),
+ comment = new CommentLinkMockup(),
+ comment2 = new CommentLinkMockup(),
+ comment3 = new CommentLinkMockup();
+ t.expect(5);
+
+ role.link(user, {
+ error: function (err, errors, obj) {
+ console.log(err, errors, obj.allProperties())
+ t.ok(false, 'Error callback for role.link(user) called even though user is valid.');
+ }
+ });
+ user.link(comment, {
+ error: function (err, errors, obj) {
+ t.same(err, 'invalid', 'err in error callback was not "invalid"');
+ t.same(errors, comment.errors, 'errors in error callback was not comment.errors');
+ t.same(comment, obj, 'obj in Error callback was not the right object.');
+ }
+ });
+ user.link(comment2, {
+ error: function (err, errors, obj) {
+ console.log(err, errors, obj.allProperties())
+ t.ok(false, 'Error callback for comment2.link(user) called even though user is valid.');
+ }
+ });
+ user.link(comment3, {
+ error: function (err, errors, obj) {
+ console.log(err, errors, obj.allProperties())
+ t.ok(false, 'Error callback for comment3.link(user) called even though user is valid.');
+ }
+ });
+ comment.p('text', ''); // makes the first comment fail
+
+ role.save({continueOnLinkError: true}, function () {
+ redis.sismember(relationsprefix + comment3.modelName + ':defaultForeign:' +
+ user.modelName + ':' + comment3.id, user.id,
+ function (err, value) {
+ t.ok(!err, 'There was a redis error');
+ t.same(value, "1", 'The comment3 relation was not saved');
+ t.done();
+ }
+ );
+ });
}
};
Please sign in to comment.
Something went wrong with that request. Please try again.