Add updateRelations on models and update generated API to use this method

This commit is contained in:
Aurelsicoko 2018-05-09 12:52:32 +02:00
parent fc44709069
commit dfec0b630b
4 changed files with 72 additions and 34 deletions

View File

@ -18,15 +18,21 @@ module.exports = {
*/
fetchAll: (params) => {
const convertedParams = strapi.utils.models.convertParams('<%= globalID.toLowerCase() %>', params);
// Convert `params` object to filters compatible with Mongo.
const filters = strapi.utils.models.convertParams('<%= globalID.toLowerCase() %>', params);
// Select field to populate.
const populate = <%= globalID %>.associations
.filter(ast => ast.autoPopulate !== false)
.map(ast => ast.alias)
.join(' ');
return <%= globalID %>
.find()
.where(convertedParams.where)
.sort(convertedParams.sort)
.skip(convertedParams.start)
.limit(convertedParams.limit)
.populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' '));
.where(filters.where)
.sort(filters.sort)
.skip(filters.start)
.limit(filters.limit)
.populate(populate);
},
/**
@ -36,9 +42,15 @@ module.exports = {
*/
fetch: (params) => {
// Select field to populate.
const populate = <%= globalID %>.associations
.filter(ast => ast.autoPopulate !== false)
.map(ast => ast.alias)
.join(' ');
return <%= globalID %>
.findOne(_.pick(params, _.keys(<%= globalID %>.schema.paths)))
.populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' '));
.populate(populate);
},
/**
@ -48,12 +60,15 @@ module.exports = {
*/
add: async (values) => {
const query = await <%= globalID %>.create(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias'))));
const data = query.toJSON ? query.toJSON() : query;
// Extract values related to relational data.
const relations = _.pick(values, <%= globalID %>.associations.map(ast => ast.alias));
const data = _.omit(values, <%= globalID %>.associations.map(ast => ast.alias));
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(data, { values }));
// Create entry with no-relational data.
const entry = await <%= globalID %>.create(data);
return query;
// Create relational data and return the entry.
return <%= globalID %>.updateRelations({ id: entry.id, values: relations });
},
/**
@ -63,11 +78,15 @@ module.exports = {
*/
edit: async (params, values) => {
// Note: The current method will return the full response of Mongo.
// To get the updated object, you have to execute the `findOne()` method
// or use the `findOneOrUpdate()` method with `{ new:true }` option.
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(_.clone(params), { values }));
return <%= globalID %>.update(params, values, { multi: true });
// Extract values related to relational data.
const relations = _.pick(values, <%= globalID %>.associations.map(a => a.alias));
const data = _.omit(values, <%= globalID %>.associations.map(a => a.alias));
// Update entry with no-relational data.
const entry = await <%= globalID %>.update(params, data, { multi: true });
// Update relational data and return the entry.
return <%= globalID %>.updateRelations(Object.assign(params, { values: relations }));
},
/**
@ -77,20 +96,31 @@ module.exports = {
*/
remove: async params => {
// Select field to populate.
const populate = <%= globalID %>.associations
.filter(ast => ast.autoPopulate !== false)
.map(ast => ast.alias)
.join(' ');
// Note: To get the full response of Mongo, use the `remove()` method
// or add spent the parameter `{ passRawResult: true }` as second argument.
const data = await <%= globalID %>.findOneAndRemove(params, {})
.populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' '));
const data = await <%= globalID %>
.findOneAndRemove(params, {})
.populate(populate);
_.forEach(<%= globalID %>.associations, async association => {
const search = (_.endsWith(association.nature, 'One')) ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } };
const update = (_.endsWith(association.nature, 'One')) ? { [association.via]: null } : { $pull: { [association.via]: data._id } };
await Promise.all(
<%= globalID %>.associations.map(async association => {
const search = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } };
const update = _.endsWith(association.nature, 'One') || association.nature === 'oneToMany' ? { [association.via]: null } : { $pull: { [association.via]: data._id } };
await strapi.models[association.model || association.collection].update(
search,
update,
{ multi: true });
});
// Retrieve model.
const model = association.plugin ?
strapi.plugins[association.plugin].models[association.model || association.collection] :
strapi.models[association.model || association.collection];
return model.update(search, update, { multi: true });
})
);
return data;
}

View File

@ -8,7 +8,7 @@
const _ = require('lodash');
module.exports = {
getModel: async function (model, plugin) {
getModel: function (model, plugin) {
return _.get(strapi.plugins, [plugin, 'models', model]) || get(strapi, ['models', model]) || undefined;
},
@ -125,6 +125,8 @@ module.exports = {
// Push the work into the flow process.
toAdd.forEach(value => {
value = _.isString(value) ? { [this.primaryKey]: value } : value;
if (association.nature === 'manyToMany' && !_.isArray(params.values[this.primaryKey] || params[this.primaryKey])) {
value[details.via] = (value[details.via] || [])
.concat([(params.values[this.primaryKey] || params[this.primaryKey])])
@ -136,7 +138,7 @@ module.exports = {
}
virtualFields.push(
module.exports.addRelation(model, {
module.exports.addRelation.call(model, {
id: value[this.primaryKey] || value.id || value._id,
values: _.pick(value, [this.primaryKey, details.via]),
foreignKey: current
@ -145,6 +147,8 @@ module.exports = {
});
toRemove.forEach(value => {
value = _.isString(value) ? { [this.primaryKey]: value } : value;
if (association.nature === 'manyToMany' && !_.isArray(params.values[this.primaryKey])) {
value[details.via] = value[details.via].filter(x => x.toString() !== params.values[this.primaryKey].toString());
} else {
@ -152,7 +156,7 @@ module.exports = {
}
virtualFields.push(
module.export.removeRelation(model, {
module.exports.removeRelation.call(model, {
id: value[this.primaryKey] || value.id || value._id,
values: _.pick(value, [this.primaryKey, details.via]),
foreignKey: current
@ -213,7 +217,7 @@ module.exports = {
// Remove relations in the other side.
toAdd.forEach(id => {
virtualFields.push(
module.exports.addRelationMorph(model, {
module.exports.addRelationMorph.call(model, {
id,
alias: association.via,
ref: this.globalId,
@ -226,7 +230,7 @@ module.exports = {
// Remove relations in the other side.
toRemove.forEach(id => {
virtualFields.push(
module.exports.removeRelationMorph(model, {
module.exports.removeRelationMorph.call(model, {
id,
alias: association.via,
ref: this.globalId,
@ -262,7 +266,7 @@ module.exports = {
.findOne({
[this.primaryKey]: params[this.primaryKey] || params.id
})
.populate(model.associations.map(x => x.alias).join(' '));
.populate(this.associations.map(x => x.alias).join(' '));
},
addRelation: async function (params) {

View File

@ -38,6 +38,10 @@
"via": "users",
"plugin": "users-permissions",
"configurable": false
},
"article": {
"model": "article",
"via": "authors"
}
}
}

View File

@ -25,7 +25,7 @@ module.exports = strapi => {
await next();
} catch (error) {
// Log error.
strapi.log.error(error);
console.error(error);
// Wrap error into a Boom's response.
ctx.status = error.status || 500;