diff --git a/lib/relation-definition.js b/lib/relation-definition.js index 3f7d4477..5ab62a55 100644 --- a/lib/relation-definition.js +++ b/lib/relation-definition.js @@ -574,6 +574,21 @@ HasMany.prototype.destroyById = function (fkId, cb) { }); }; +var throughKeys = function(definition) { + var modelThrough = definition.modelThrough; + var pk2 = definition.modelTo.definition.idName(); + + if (definition.typeTo) { // polymorphic + var fk1 = definition.keyTo; + var fk2 = definition.keyThrough; + } else { + var fk1 = findBelongsTo(modelThrough, definition.modelFrom, + definition.keyFrom); + var fk2 = findBelongsTo(modelThrough, definition.modelTo, pk2); + } + return [fk1, fk2]; +} + /** * Find a related item by foreign key * @param {*} fkId The foreign key value @@ -664,14 +679,9 @@ HasManyThrough.prototype.create = function create(data, done) { // The primary key for the target model var pk2 = definition.modelTo.definition.idName(); - if (definition.typeTo) { // polymorphic - var fk1 = definition.keyTo; - var fk2 = definition.keyThrough; - } else { - var fk1 = findBelongsTo(modelThrough, definition.modelFrom, - definition.keyFrom); - var fk2 = findBelongsTo(modelThrough, definition.modelTo, pk2); - } + var keys = throughKeys(definition); + var fk1 = keys[0]; + var fk2 = keys[1]; var d = {}; d[fk1] = modelInstance[definition.keyFrom]; @@ -694,6 +704,8 @@ HasManyThrough.prototype.create = function create(data, done) { }); }; + + /** * Add the target model instance to the 'hasMany' relation * @param {Object|ID} acInst The actual instance or id value @@ -706,14 +718,13 @@ HasManyThrough.prototype.add = function (acInst, done) { var data = {}; var query = {}; - - var fk1 = findBelongsTo(modelThrough, definition.modelFrom, - definition.keyFrom); - + // The primary key for the target model var pk2 = definition.modelTo.definition.idName(); - var fk2 = findBelongsTo(modelThrough, definition.modelTo, pk2); + var keys = throughKeys(definition); + var fk1 = keys[0]; + var fk2 = keys[1]; query[fk1] = this.modelInstance[pk1]; query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst; @@ -724,6 +735,7 @@ HasManyThrough.prototype.add = function (acInst, done) { data[fk1] = this.modelInstance[pk1]; data[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst; + definition.applyProperties(this.modelInstance, data); // Create an instance of the through model @@ -749,15 +761,12 @@ HasManyThrough.prototype.exists = function (acInst, done) { var data = {}; var query = {}; - var fk1 = findBelongsTo(modelThrough, definition.modelFrom, - definition.keyFrom); - // The primary key for the target model var pk2 = definition.modelTo.definition.idName(); - - var fk2 = findBelongsTo(modelThrough, definition.modelTo, pk2); - - query[fk1] = this.modelInstance[pk1]; + + var keys = throughKeys(definition); + var fk1 = keys[0]; + var fk2 = keys[1]; query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst; @@ -781,13 +790,12 @@ HasManyThrough.prototype.remove = function (acInst, done) { var query = {}; - var fk1 = findBelongsTo(modelThrough, definition.modelFrom, - definition.keyFrom); - // The primary key for the target model var pk2 = definition.modelTo.definition.idName(); - - var fk2 = findBelongsTo(modelThrough, definition.modelTo, pk2); + + var keys = throughKeys(definition); + var fk1 = keys[0]; + var fk2 = keys[1]; query[fk1] = this.modelInstance[pk1]; query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst; @@ -795,7 +803,7 @@ HasManyThrough.prototype.remove = function (acInst, done) { var filter = { where: query }; definition.applyScope(this.modelInstance, filter); - + modelThrough.deleteAll(filter.where, function (err) { if (!err) { self.removeFromCache(query[fk2]); diff --git a/test/relations.test.js b/test/relations.test.js index 824d710f..fe2751d6 100644 --- a/test/relations.test.js +++ b/test/relations.test.js @@ -792,7 +792,7 @@ describe('relations', function () { }); it('should create polymorphic relation - author', function (done) { - Author.create({ id: 3, name: 'Author 1' }, function (err, author) { + Author.create({ id: 4, name: 'Author 1' }, function (err, author) { author.pictures.create({ name: 'Author Pic 1' }, function (err, p) { should.not.exist(err); p.id.should.equal(1); @@ -819,14 +819,14 @@ describe('relations', function () { PictureLink.findOne(function(err, link) { should.not.exist(err); link.pictureId.should.equal(1); - link.imageableId.should.equal(3); + link.imageableId.should.equal(4); link.imageableType.should.equal('Author'); done(); }); }); it('should get polymorphic relation through model - author', function (done) { - Author.findById(3, function(err, author) { + Author.findById(4, function(err, author) { should.not.exist(err); author.name.should.equal('Author 1'); author.pictures(function(err, pics) { @@ -851,6 +851,68 @@ describe('relations', function () { }); }); }); + + it('should include polymorphic items', function (done) { + Author.find({ include: 'pictures' }, function(err, authors) { + authors.should.have.length(1); + authors[0].pictures(function(err, pics) { + pics[0].name.should.equal('Author Pic 1'); + pics[1].name.should.equal('Author Pic 2'); + done(); + }); + }); + }); + + it('should add to a polymorphic relation - author', function (done) { + Author.findById(4, function(err, author) { + Picture.create({ id: 7, name: 'Example' }, function(err, p) { + author.pictures.add(p, function(err, link) { + link.should.be.instanceof(PictureLink); + link.pictureId.should.equal(7); + link.imageableId.should.equal(4); + link.imageableType.should.equal('Author'); + done(); + }); + }); + }); + }); + + it('should create polymorphic through model', function (done) { + PictureLink.findOne({ where: { pictureId: 7 } }, function(err, link) { + should.not.exist(err); + link.pictureId.should.equal(7); + link.imageableId.should.equal(4); + link.imageableType.should.equal('Author'); + done(); + }); + }); + + it('should check if polymorphic relation exists - author', function (done) { + Author.findById(4, function(err, author) { + author.pictures.exists(7, function(err, exists) { + exists.should.be.true; + done(); + }); + }); + }); + + it('should remove from a polymorphic relation - author', function (done) { + Author.findById(4, function(err, author) { + author.pictures.remove(7, function(err) { + should.not.exist(err); + done(); + }); + }); + }); + + it('should check if polymorphic relation exists - author', function (done) { + Author.findById(4, function(err, author) { + author.pictures.exists(7, function(err, exists) { + exists.should.be.false; + done(); + }); + }); + }); });