Implemented polymorphic hasMany through inverse

Added option invert: true to enable inverse polymorphic hasMany
relations.

Fixed missing fk1 in query of HasManyThrough.prototype.exists.
This commit is contained in:
Fabien Franzen 2014-07-26 21:11:25 +02:00
parent d1896553fd
commit 5e30ec8637
2 changed files with 86 additions and 10 deletions

View File

@ -371,8 +371,10 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
if (typeof params.polymorphic === 'string') {
var polymorphic = params.polymorphic;
fk = i8n.camelize(polymorphic + '_id', true);
typeTo = i8n.camelize(polymorphic + '_type', true);
if (!params.invert) {
fk = i8n.camelize(polymorphic + '_id', true);
}
if (!params.through) {
modelTo.dataSource.defineProperty(modelTo.modelName, typeTo, { type: 'string', index: true });
}
@ -445,7 +447,11 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
definition.applyScope(this, filter);
if (params.through) {
if (params.through && params.polymorphic && params.invert) {
filter.where[typeTo] = modelTo.modelName; // overwrite
filter.collect = params.polymorphic;
filter.include = filter.collect;
} else if (params.through) {
filter.collect = i8n.camelize(modelTo.modelName, true);
filter.include = filter.collect;
}
@ -758,7 +764,6 @@ HasManyThrough.prototype.exists = function (acInst, done) {
var modelThrough = definition.modelThrough;
var pk1 = definition.keyFrom;
var data = {};
var query = {};
// The primary key for the target model
@ -768,12 +773,14 @@ HasManyThrough.prototype.exists = function (acInst, done) {
var fk1 = keys[0];
var fk2 = keys[1];
query[fk1] = this.modelInstance[pk1];
query[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst;
data[fk1] = this.modelInstance[pk1];
data[fk2] = (acInst instanceof definition.modelTo) ? acInst[pk2] : acInst;
var filter = { where: query };
modelThrough.count(query, function(err, ac) {
definition.applyScope(this.modelInstance, filter);
modelThrough.count(filter.where, function(err, ac) {
done(err, ac > 0);
});
};

View File

@ -788,6 +788,8 @@ describe('relations', function () {
it('can be declared', function (done) {
Author.hasAndBelongsToMany(Picture, { through: PictureLink, polymorphic: 'imageable' });
Reader.hasAndBelongsToMany(Picture, { through: PictureLink, polymorphic: 'imageable' });
Picture.hasMany(Author, { through: PictureLink, polymorphic: 'imageable', invert: true });
Picture.hasMany(Reader, { through: PictureLink, polymorphic: 'imageable', invert: true });
db.automigrate(done);
});
@ -821,7 +823,11 @@ describe('relations', function () {
link.pictureId.should.equal(1);
link.imageableId.should.equal(4);
link.imageableType.should.equal('Author');
done();
link.imageable(function(err, imageable) {
imageable.should.be.instanceof(Author);
imageable.id.should.equal(4);
done();
});
});
});
@ -856,6 +862,7 @@ describe('relations', function () {
Author.find({ include: 'pictures' }, function(err, authors) {
authors.should.have.length(1);
authors[0].pictures(function(err, pics) {
pics.should.have.length(2);
pics[0].name.should.equal('Author Pic 1');
pics[1].name.should.equal('Author Pic 2');
done();
@ -878,7 +885,7 @@ describe('relations', function () {
});
it('should create polymorphic through model', function (done) {
PictureLink.findOne({ where: { pictureId: 7 } }, function(err, link) {
PictureLink.findOne({ where: { pictureId: 7, imageableType: 'Author' } }, function(err, link) {
should.not.exist(err);
link.pictureId.should.equal(7);
link.imageableId.should.equal(4);
@ -887,6 +894,57 @@ describe('relations', function () {
});
});
it('should add to a polymorphic relation - author', function (done) {
Author.create({ id: 5, name: 'Author 2' }, function (err, author) {
author.pictures.add(7, function (err, p) {
should.not.exist(err);
done();
});
});
});
it('should add to a polymorphic relation - author', function (done) {
Reader.create({ id: 5, name: 'Reader 2' }, function (err, reader) {
reader.pictures.add(7, function (err, p) {
should.not.exist(err);
done();
});
});
});
it('should get the inverse polymorphic relation - author', function (done) {
Picture.findById(7, function(err, p) {
p.authors(function(err, authors) {
authors.should.have.length(2);
authors[0].name.should.equal('Author 1');
authors[1].name.should.equal('Author 2');
done();
});
});
});
it('should get the inverse polymorphic relation - reader', function (done) {
Picture.findById(7, function(err, p) {
p.readers(function(err, readers) {
readers.should.have.length(1);
readers[0].name.should.equal('Reader 2');
done();
});
});
});
it('should find polymorphic items - author', function (done) {
Author.findById(4, function(err, author) {
author.pictures(function(err, pics) {
pics.should.have.length(3);
pics[0].name.should.equal('Author Pic 1');
pics[1].name.should.equal('Author Pic 2');
pics[2].name.should.equal('Example');
done();
});
});
});
it('should check if polymorphic relation exists - author', function (done) {
Author.findById(4, function(err, author) {
author.pictures.exists(7, function(err, exists) {
@ -905,6 +963,17 @@ describe('relations', function () {
});
});
it('should find polymorphic items - author', function (done) {
Author.findById(4, function(err, author) {
author.pictures(function(err, pics) {
pics.should.have.length(2);
pics[0].name.should.equal('Author Pic 1');
pics[1].name.should.equal('Author Pic 2');
done();
});
});
});
it('should check if polymorphic relation exists - author', function (done) {
Author.findById(4, function(err, author) {
author.pictures.exists(7, function(err, exists) {