Skip to content

Commit

Permalink
added a validation option for each path to check if the parent actual…
Browse files Browse the repository at this point in the history
…ly exists for a given path
  • Loading branch information
sabymike committed Feb 28, 2014
1 parent d7241a9 commit d6def79
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 5 deletions.
55 changes: 51 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ function validatePath(relationshipPath) {
{
if ( _.isUndefined(relationshipPathOptions.ref) )
{
throw new Error("Relationship " + relationshipPath.path + " requires a ref");
return new Error("Relationship " + relationshipPath.path + " requires a ref");
}

if ( _.isUndefined(relationshipPathOptions.childPath) )
{
throw new Error("Relationship " + relationshipPath.path + " requires a childPath for its parent");
return new Error("Relationship " + relationshipPath.path + " requires a childPath for its parent");
}
}
else
{
throw new Error("Mission options for relationship " + relationshipPathName);
return new Error("Mission options for relationship " + relationshipPathName);
}
}

Expand All @@ -56,7 +56,54 @@ module.exports = exports = function relationship(schema, options) {
{
throw new Error("No relationship path defined");
}
validatePath(relationshipPath);
var validationError = validatePath(relationshipPath);
if ( validationError )
{
throw validationError;
}
else
{
var opts = optionsForRelationship(relationshipPath);
if ( opts.validateExistence )
{
if ( _.isFunction(relationshipPath.options.type) )
{
schema.path(relationshipPathName).validate(function(value, response) {
var relationshipTargetModel = this.db.model(opts.ref);
relationshipTargetModel.findById(value, function(err, result) {
if ( err || !result )
{
response(false);
}
else
{
response(true);
}
});
}, "Relationship entity " + opts.ref + " does not exist");
}
else if ( _.isObject(relationshipPath.options.type) )
{
schema.path(relationshipPathName).validate(function(value, response) {
var relationshipTargetModel = this.db.model(opts.ref);
relationshipTargetModel.find({_id: { $in: value }}, function(err, result) {
// check if there is an error, if the result didn't return anything,
// or we didn't find the same amount of entities as the set value
//expects us to
if ( ( err || !result ) ||
( result && result.length !== value.length ) )
{
response(false);
}
else
{
response(true);
}
});
}, "Relationship entity " + opts.ref + " does not exist");
}
}
}
});

schema.pre('save', function(done) {
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":"mongoose-relationship",
"version":"0.0.2",
"version":"0.0.4",
"description":"mongoose plugin to create maintain one-many and many-many bidirectional relationships between two schemas",
"main":"index.js",
"scripts": {
Expand Down
100 changes: 100 additions & 0 deletions test/relationshipSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,106 @@ describe("Schema Key Tests", function() {
});
});

describe("Parent Existence", function() {
describe("Single Parent", function() {
var Child, Parent;
before(function() {
var ParentSchema = new Schema({
children:[{type:Schema.ObjectId, ref:"ChildOneManyValidate" }]
});
Parent = mongoose.model("ParentOneManyValidate", ParentSchema);

var ChildSchema = new Schema({
name:String,
parent: { type: Schema.ObjectId, ref:"ParentOneManyValidate", childPath:"children", validateExistence:true }
});
ChildSchema.plugin(relationship, { relationshipPathName: 'parent' });
Child = mongoose.model("ChildOneManyValidate", ChildSchema);
});

beforeEach(function() {
this.child = new Child({parent:new mongoose.Types.ObjectId()});
});

it("should validate the existence of the relationship before saving if the flag is set", function(done) {
this.child.save(function(err, child) {
should.exist(err);
err.errors.parent.message.should.eql("Relationship entity ParentOneManyValidate does not exist");
done();
});
});

it('should create the relationship if the parent actually exists', function(done) {
var parent = new Parent();
this.child.parent = parent;

var self = this;
parent.save(function(err, parent) {
self.child.save(function(err, child) {
child.should.exist;
done(err);
});
});
});
});

describe("Multiple Parents", function() {
var Child, Parent;
before(function() {
var ParentSchema = new Schema({
children:[{type:Schema.ObjectId, ref:"ChildManyManyValidate" }]
});
Parent = mongoose.model("ParentManyManyValidate", ParentSchema);

var ChildSchema = new Schema({
name:String,
parents: [{ type: Schema.ObjectId, ref:"ParentManyManyValidate", childPath:"children", validateExistence:true }]
});
ChildSchema.plugin(relationship, { relationshipPathName: 'parents' });
Child = mongoose.model("ChildManyManyValidate", ChildSchema);
});

beforeEach(function() {
this.child = new Child({parents:[new mongoose.Types.ObjectId()]});
});

it("should validate the existence of the relationship before saving if the flag is set", function(done) {
this.child.save(function(err, child) {
should.exist(err);
err.errors.parents.message.should.eql("Relationship entity ParentManyManyValidate does not exist");
done();
});
});

it('should fail if just one id in the relationship list does not exist', function(done) {
var parent = new Parent();
this.child.parents = [parent, new mongoose.Types.ObjectId()];

var self = this;
parent.save(function(err, parent) {
self.child.save(function(err, child) {
should.exist(err);
err.errors.parents.message.should.eql("Relationship entity ParentManyManyValidate does not exist");
done();
});
});
});

it('should create the relationship if the parent actually exists', function(done) {
var parent = new Parent();
this.child.parents = [parent];

var self = this;
parent.save(function(err, parent) {
self.child.save(function(err, child) {
child.should.exist;
done(err);
});
});
});
});
});

describe("One-To-Many", function() {
var Child, Parent;
before(function() {
Expand Down

0 comments on commit d6def79

Please sign in to comment.