[WIP] Polymorphic assocations

This commit is contained in:
Aurelsicoko 2018-02-09 10:43:09 +01:00
parent b90239b100
commit 824567de0d
4 changed files with 72 additions and 7 deletions

File diff suppressed because one or more lines are too long

View File

@ -135,7 +135,18 @@ module.exports = function (strapi) {
}); });
if (!plugin) { if (!plugin) {
global[definition.globalName] = instance.model(definition.globalName, collection.schema, definition.collectionName); // Enhance schema with polymorphic relationships.
const morphs = _.pickBy(definition.loadedModel, model => {
return model.type === 'discriminator';
});
if (_.size(morphs) > 0) {
const morph = morphs[Object.keys(morphs)[0]];
global[definition.globalName] = global[morph.ref].discriminator(morph.discriminator, collection.schema);
} else {
global[definition.globalName] = instance.model(definition.globalName, collection.schema, definition.collectionName);
}
} else { } else {
instance.model(definition.globalName, collection.schema, definition.collectionName); instance.model(definition.globalName, collection.schema, definition.collectionName);
} }
@ -195,10 +206,23 @@ module.exports = function (strapi) {
// Call this callback function after we are done parsing // Call this callback function after we are done parsing
// all attributes for relationships-- see below. // all attributes for relationships-- see below.
const done = _.after(_.size(definition.attributes), () => { const done = _.after(_.size(definition.attributes), () => {
// Generate schema without virtual populate // Extract discriminator (morphTo side)
_.set(strapi.config.hook.settings.mongoose, 'collections.' + mongooseUtils.toCollectionName(definition.globalName) + '.schema', new instance.Schema(_.omitBy(definition.loadedModel, model => { const discriminators = _.pickBy(definition.loadedModel, model => {
return model.type === 'virtual'; return model.hasOwnProperty('discriminatorKey');
}))); });
const options = {};
if (_.size(discriminators) > 0) {
options.discriminatorKey = 'type';
}
// Generate schema without virtual populate & discriminators.
let schema = new instance.Schema(_.omitBy(definition.loadedModel, model => {
return model.type === 'virtual' || model.type === 'discriminator' || model.hasOwnProperty('discriminatorKey');
}), options);
_.set(strapi.config.hook.settings.mongoose, 'collections.' + mongooseUtils.toCollectionName(definition.globalName) + '.schema', schema);
loadedAttributes(); loadedAttributes();
}); });
@ -292,6 +316,22 @@ module.exports = function (strapi) {
} }
break; break;
} }
case 'morphOne': {
const discriminator = plugin ? `${plugin}_${model.toLowerCase()}` : model.toLowerCase();
const ref = details.plugin ? strapi.plugins[details.plugin].models[details.model].globalId : strapi.models[details.model].globalId;
definition.loadedModel[name] = {
type: 'discriminator',
ref,
discriminator
}
break;
}
case 'morphTo': {
definition.loadedModel[name] = {
discriminatorKey: 'kind'
};
}
default: default:
break; break;
} }

View File

@ -36,6 +36,10 @@
"via": "users", "via": "users",
"plugin": "users-permissions", "plugin": "users-permissions",
"configurable": false "configurable": false
},
"avatar": {
"model": "upload",
"via": "related"
} }
} }
} }

View File

@ -94,6 +94,8 @@ module.exports = {
types.other = 'collectionD'; types.other = 'collectionD';
} else if (relatedAttribute.hasOwnProperty('model')) { } else if (relatedAttribute.hasOwnProperty('model')) {
types.other = 'model'; types.other = 'model';
} else if (relatedAttribute.hasOwnProperty('key')) {
types.other = 'morphTo';
} }
} else if (association.hasOwnProperty('via') && association.hasOwnProperty('model')) { } else if (association.hasOwnProperty('via') && association.hasOwnProperty('model')) {
types.current = 'modelD'; types.current = 'modelD';
@ -111,6 +113,8 @@ module.exports = {
// Break loop // Break loop
return false; return false;
} else if (attribute.hasOwnProperty('key')) {
types.other = 'morphTo'; // MorphTo
} }
}); });
}); });
@ -156,9 +160,26 @@ module.exports = {
} }
}); });
}); });
} else if (association.hasOwnProperty('key')) {
types.current = 'morphTo';
} }
if (types.current === 'modelD' && types.other === 'model') { if (types.current === 'morphTo') {
return {
nature: 'morphTo',
verbose: 'morphTo'
};
} else if (types.current === 'modelD' && types.other === 'morphTo') {
return {
nature: 'oneToOne',
verbose: 'morphOne'
};
} else if (types.current === 'collection' && types.other === 'morphTo') {
return {
nature: 'oneToMany',
verbose: 'morphMany'
};
} else if (types.current === 'modelD' && types.other === 'model') {
return { return {
nature: 'oneToOne', nature: 'oneToOne',
verbose: 'belongsTo' verbose: 'belongsTo'