Implemented polymorphic hasOne
Signed-off-by: Fabien Franzen <info@atelierfabien.be>
This commit is contained in:
parent
295e6fc1f1
commit
00dfe563eb
|
@ -101,8 +101,9 @@ RelationDefinition.prototype.toJSON = function () {
|
||||||
*/
|
*/
|
||||||
RelationDefinition.prototype.applyScope = function(modelInstance, filter) {
|
RelationDefinition.prototype.applyScope = function(modelInstance, filter) {
|
||||||
filter.where = filter.where || {};
|
filter.where = filter.where || {};
|
||||||
if (this.type !== 'belongsTo' && typeof this.typeTo === 'string') {
|
if ((this.type !== 'belongsTo' || this.type === 'hasOne')
|
||||||
filter.where[this.typeTo] = this.modelFrom.modelName; // polymorphic
|
&& typeof this.typeTo === 'string') { // polymorphic
|
||||||
|
filter.where[this.typeTo] = this.modelFrom.modelName;
|
||||||
}
|
}
|
||||||
if (typeof this.scope === 'function') {
|
if (typeof this.scope === 'function') {
|
||||||
var scope = this.scope.call(this, modelInstance, filter);
|
var scope = this.scope.call(this, modelInstance, filter);
|
||||||
|
@ -131,8 +132,9 @@ RelationDefinition.prototype.applyProperties = function(modelInstance, target) {
|
||||||
target[key] = modelInstance[k];
|
target[key] = modelInstance[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.type !== 'belongsTo' && typeof this.typeTo === 'string') {
|
if ((this.type !== 'belongsTo' || this.type === 'hasOne')
|
||||||
target[this.typeTo] = this.modelFrom.modelName; // polymorphic
|
&& typeof this.typeTo === 'string') { // polymorphic
|
||||||
|
target[this.typeTo] = this.modelFrom.modelName;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -365,10 +367,10 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
|
||||||
var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true);
|
var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true);
|
||||||
|
|
||||||
var idName = modelFrom.dataSource.idName(modelFrom.modelName) || 'id';
|
var idName = modelFrom.dataSource.idName(modelFrom.modelName) || 'id';
|
||||||
var polymorphic, typeTo;
|
var typeTo;
|
||||||
|
|
||||||
if (typeof params.polymorphic === 'string') {
|
if (typeof params.polymorphic === 'string') {
|
||||||
polymorphic = params.polymorphic;
|
var polymorphic = params.polymorphic;
|
||||||
fk = i8n.camelize(polymorphic + '_id', true);
|
fk = i8n.camelize(polymorphic + '_id', true);
|
||||||
typeTo = i8n.camelize(polymorphic + '_type', true);
|
typeTo = i8n.camelize(polymorphic + '_type', true);
|
||||||
if (!params.through) {
|
if (!params.through) {
|
||||||
|
@ -1049,15 +1051,17 @@ RelationDefinition.hasAndBelongsToMany = function hasAndBelongsToMany(modelFrom,
|
||||||
if (params.model) {
|
if (params.model) {
|
||||||
modelTo = params.model;
|
modelTo = params.model;
|
||||||
} else {
|
} else {
|
||||||
modelTo = lookupModel(models, i8n.singularize(modelTo)) ||
|
modelTo = lookupModel(models, i8n.singularize(modelTo)) || modelTo;
|
||||||
modelTo;
|
|
||||||
}
|
}
|
||||||
if (typeof modelTo === 'string') {
|
if (typeof modelTo === 'string') {
|
||||||
throw new Error('Could not find "' + modelTo + '" relation for ' + modelFrom.modelName);
|
throw new Error('Could not find "' + modelTo + '" relation for ' + modelFrom.modelName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPolymorphic = (typeof params.polymorphic === 'string');
|
||||||
|
|
||||||
if (!params.through) {
|
if (!params.through) {
|
||||||
|
if (isPolymorphic) throw new Error('Polymorphic relations need a through model');
|
||||||
var name1 = modelFrom.modelName + modelTo.modelName;
|
var name1 = modelFrom.modelName + modelTo.modelName;
|
||||||
var name2 = modelTo.modelName + modelFrom.modelName;
|
var name2 = modelTo.modelName + modelFrom.modelName;
|
||||||
params.through = lookupModel(models, name1) || lookupModel(models, name2) ||
|
params.through = lookupModel(models, name1) || lookupModel(models, name2) ||
|
||||||
|
@ -1066,7 +1070,7 @@ RelationDefinition.hasAndBelongsToMany = function hasAndBelongsToMany(modelFrom,
|
||||||
|
|
||||||
var options = {as: params.as, through: params.through};
|
var options = {as: params.as, through: params.through};
|
||||||
|
|
||||||
if (typeof params.polymorphic === 'string') {
|
if (isPolymorphic) {
|
||||||
options.polymorphic = params.polymorphic;
|
options.polymorphic = params.polymorphic;
|
||||||
var accessor = params.through.prototype[params.polymorphic];
|
var accessor = params.through.prototype[params.polymorphic];
|
||||||
if (typeof accessor !== 'function') { // declare once
|
if (typeof accessor !== 'function') { // declare once
|
||||||
|
@ -1113,6 +1117,16 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) {
|
||||||
var relationName = params.as || i8n.camelize(modelTo.modelName, true);
|
var relationName = params.as || i8n.camelize(modelTo.modelName, true);
|
||||||
|
|
||||||
var fk = params.foreignKey || i8n.camelize(modelFrom.modelName + '_id', true);
|
var fk = params.foreignKey || i8n.camelize(modelFrom.modelName + '_id', true);
|
||||||
|
var typeTo;
|
||||||
|
|
||||||
|
if (typeof params.polymorphic === 'string') {
|
||||||
|
var polymorphic = params.polymorphic;
|
||||||
|
fk = i8n.camelize(polymorphic + '_id', true);
|
||||||
|
typeTo = i8n.camelize(polymorphic + '_type', true);
|
||||||
|
if (!params.through) {
|
||||||
|
modelTo.dataSource.defineProperty(modelTo.modelName, typeTo, { type: 'string', index: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var relationDef = modelFrom.relations[relationName] = new RelationDefinition({
|
var relationDef = modelFrom.relations[relationName] = new RelationDefinition({
|
||||||
name: relationName,
|
name: relationName,
|
||||||
|
@ -1120,6 +1134,7 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) {
|
||||||
modelFrom: modelFrom,
|
modelFrom: modelFrom,
|
||||||
keyFrom: pk,
|
keyFrom: pk,
|
||||||
keyTo: fk,
|
keyTo: fk,
|
||||||
|
typeTo: typeTo,
|
||||||
modelTo: modelTo,
|
modelTo: modelTo,
|
||||||
properties: params.properties,
|
properties: params.properties,
|
||||||
options: params.options
|
options: params.options
|
||||||
|
|
|
@ -528,6 +528,101 @@ describe('relations', function () {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('polymorphic hasOne', function () {
|
||||||
|
before(function (done) {
|
||||||
|
db = getSchema();
|
||||||
|
Picture = db.define('Picture', {name: String});
|
||||||
|
Author = db.define('Author', {name: String});
|
||||||
|
Reader = db.define('Reader', {name: String});
|
||||||
|
|
||||||
|
db.automigrate(function () {
|
||||||
|
Picture.destroyAll(function () {
|
||||||
|
Author.destroyAll(function () {
|
||||||
|
Reader.destroyAll(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can be declared', function (done) {
|
||||||
|
Author.hasOne(Picture, { as: 'avatar', polymorphic: 'imageable' });
|
||||||
|
Reader.hasOne(Picture, { as: 'mugshot', polymorphic: 'imageable' });
|
||||||
|
Picture.belongsTo('imageable', { polymorphic: true });
|
||||||
|
db.automigrate(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create polymorphic relation - author', function (done) {
|
||||||
|
Author.create({ id: 8, name: 'Author 1' }, function (err, author) {
|
||||||
|
author.avatar.create({ name: 'Avatar' }, function (err, p) {
|
||||||
|
should.not.exist(err);
|
||||||
|
should.exist(p);
|
||||||
|
p.imageableId.should.equal(author.id);
|
||||||
|
p.imageableType.should.equal('Author');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create polymorphic relation - reader', function (done) {
|
||||||
|
Reader.create({ id: 6, name: 'Reader 1' }, function (err, reader) {
|
||||||
|
reader.mugshot.create({ name: 'Mugshot' }, function (err, p) {
|
||||||
|
should.not.exist(err);
|
||||||
|
should.exist(p);
|
||||||
|
p.imageableId.should.equal(reader.id);
|
||||||
|
p.imageableType.should.equal('Reader');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find polymorphic relation - author', function (done) {
|
||||||
|
Author.findOne(function (err, author) {
|
||||||
|
author.avatar(function (err, p) {
|
||||||
|
should.not.exist(err);
|
||||||
|
p.name.should.equal('Avatar');
|
||||||
|
p.imageableId.should.equal(author.id);
|
||||||
|
p.imageableType.should.equal('Author');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find polymorphic relation - reader', function (done) {
|
||||||
|
Reader.findOne(function (err, reader) {
|
||||||
|
reader.mugshot(function (err, p) {
|
||||||
|
should.not.exist(err);
|
||||||
|
p.name.should.equal('Mugshot');
|
||||||
|
p.imageableId.should.equal(reader.id);
|
||||||
|
p.imageableType.should.equal('Reader');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find inverse polymorphic relation - author', function (done) {
|
||||||
|
Picture.findOne({ where: { name: 'Avatar' } }, function (err, p) {
|
||||||
|
p.imageable(function (err, imageable) {
|
||||||
|
should.not.exist(err);
|
||||||
|
imageable.should.be.instanceof(Author);
|
||||||
|
imageable.name.should.equal('Author 1');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find inverse polymorphic relation - reader', function (done) {
|
||||||
|
Picture.findOne({ where: { name: 'Mugshot' } }, function (err, p) {
|
||||||
|
p.imageable(function (err, imageable) {
|
||||||
|
should.not.exist(err);
|
||||||
|
imageable.should.be.instanceof(Reader);
|
||||||
|
imageable.name.should.equal('Reader 1');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('polymorphic hasMany', function () {
|
describe('polymorphic hasMany', function () {
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
db = getSchema();
|
db = getSchema();
|
||||||
|
|
Loading…
Reference in New Issue