polymorphics can now be declared using object

This commit is contained in:
Fabien Franzen 2014-07-28 10:44:26 +02:00
parent 4e76c2a77f
commit 7ddfbb6409
2 changed files with 33 additions and 11 deletions

View File

@ -328,6 +328,19 @@ function lookupModel(models, modelName) {
}
}
/*!
* Normalize polymorphic parameters
* @param {Object|String} params Name of the polymorphic relation or params
* @returns {Object} The normalized parameters
*/
function polymorphicParams(params) {
if (typeof params === 'string') params = { as: params };
if (typeof params.as !== 'string') params.as = 'reference'; // default
params.foreignKey = params.foreignKey || i8n.camelize(params.as + '_id', true);
params.discriminator = params.discriminator || i8n.camelize(params.as + '_type', true);
return params;
};
/**
* Define a "one to many" relationship by specifying the model name
*
@ -369,11 +382,11 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
var idName = modelFrom.dataSource.idName(modelFrom.modelName) || 'id';
var discriminator;
if (typeof params.polymorphic === 'string') {
var polymorphic = params.polymorphic;
discriminator = i8n.camelize(polymorphic + '_type', true);
if (params.polymorphic) {
var polymorphic = polymorphicParams(params.polymorphic);
discriminator = polymorphic.discriminator;
if (!params.invert) {
fk = i8n.camelize(polymorphic + '_id', true);
fk = polymorphic.foreignKey;
}
if (!params.through) {
modelTo.dataSource.defineProperty(modelTo.modelName, discriminator, { type: 'string', index: true });
@ -857,16 +870,22 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
}
if (params.polymorphic) {
var polymorphic = modelTo;
if (params.polymorphic === true) {
// modelTo will be the name of the polymorphic relation (string)
var polymorphic = polymorphicParams(modelTo);
} else {
var polymorphic = polymorphicParams(params.polymorphic);
}
modelTo = null; // will lookup dynamically
var idName = params.idName || 'id';
var relationName = params.as || i8n.camelize(polymorphic, true);
var fk = i8n.camelize(polymorphic + '_id', true);
var discriminator = i8n.camelize(polymorphic + '_type', true);
var relationName = params.as || polymorphic.as;
var fk = polymorphic.foreignKey;
var discriminator = polymorphic.discriminator;
if (typeof params.idType === 'string') { // explicit key type
modelFrom.dataSource.defineProperty(modelFrom.modelName, fk, { type: params.idType, index: true });
if (typeof polymorphic.idType === 'string') { // explicit key type
modelFrom.dataSource.defineProperty(modelFrom.modelName, fk, { type: polymorphic.idType, index: true });
} else { // try to use the same foreign key type as modelFrom
modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelFrom.modelName);
}

View File

@ -641,7 +641,10 @@ describe('relations', function () {
it('can be declared', function (done) {
Author.hasMany(Picture, { polymorphic: 'imageable' });
Reader.hasMany(Picture, { polymorphic: 'imageable' });
Reader.hasMany(Picture, { polymorphic: { // alt syntax
as: 'imageable', foreignKey: 'imageableId',
discriminator: 'imageableType'
} });
Picture.belongsTo('imageable', { polymorphic: true });
db.automigrate(done);
});