I create a new project:
$ mrt create sandbox
$ mrt remove autopublish
$ mrt add collection2
And use the following code to create a simple collection with a unique constraint on a key
SandBoxCollection = new Meteor.Collection('sandboxcoll', {
schema: new SimpleSchema({
title: {
type: String,
min: 3,
unique: true,
index: true
}
})
});
if (Meteor.isServer) {
Meteor.publish('sandboxpub', function() {
return SandBoxCollection.find();
});
}
if (Meteor.isClient) {
Meteor.subscribe('sandboxpub');
}
Meteor.methods({
create: function(doc) {
var docId = SandBoxCollection.insert(doc, {validationContext: 'create'}, function(err, res) {
if (err) {
throw new Meteor.Error(333, SandBoxCollection.simpleSchema().namedContext('create').invalidKeys());
}
return res;
});
return docId;
}
});
I set up a simple collection, pub/sub and a method that I can use for inserts.
Then I use the browser console to issue the following commands
Let's first create a document:
Meteor.call('create', {title: 'abcd01'}, function(e,r){
console.log(e ? e : r);
});
Now let's try inserting a duplicate directly using collection.insert():
SandBoxCollection.insert({title: 'abcd01'}, function(e,r) {
console.log('error: ');
console.log(e);
console.log('errorkeys: ');
console.log(SandBoxCollection.simpleSchema().namedContext().invalidKeys());
console.log('result: ');
console.log(r);
});
We can see a proper 333 error handled by the callback and logged to the console.
Now try inserting a duplicate using the method:
Meteor.call('create', {title: 'abcd01'}, function(e,r){
console.log(e ? e : r);
});
Notice that, unlike the direct insert, the method throws an uncaught exception! Furthermore, the error is thrown from our custom throw and it has error code 333.
Why is this not handled properly? What can I do to mitigate this so that I can do something with the error (notify the user, redirect to the original documents page etc)
As of February 2014, this is an enhancement request on collection2 issue tracker at https://github.com/aldeed/meteor-collection2/issues/59
The current workaround (on the server) is to catch the error separately and feed it into a custom Meteor.Error as in:
Note: This is a generic insert method that takes the namespaced collection name as a parameter and a document. It is intended to be called from the client side with a callback function which returns either the result as a document id or an error object.