diff --git a/packages/strapi-generate-migrations/lib/after.js b/packages/strapi-generate-migrations/lib/after.js index f3e07d2ffb..b389e96516 100755 --- a/packages/strapi-generate-migrations/lib/after.js +++ b/packages/strapi-generate-migrations/lib/after.js @@ -76,10 +76,14 @@ module.exports = function afterGenerate(scope, cb) { return _.omitBy(model, _.isFunction); }); + const modelsKeyLowercased = _.mapKeys(models, function (model, key) { + return key.toLowerCase(); + }); + const historyFile = path.resolve(scope.rootPath, 'data', 'migrations', '.history'); // And rewrite it with the beautify node module. - fs.writeFile(historyFile, beautify(JSON.stringify(models), { + fs.writeFile(historyFile, beautify(JSON.stringify(modelsKeyLowercased), { indent_size: 2, keep_function_indentation: true, space_before_conditional: true, diff --git a/packages/strapi-generate-migrations/lib/before.js b/packages/strapi-generate-migrations/lib/before.js index 304521e7a7..b5945071a5 100755 --- a/packages/strapi-generate-migrations/lib/before.js +++ b/packages/strapi-generate-migrations/lib/before.js @@ -96,8 +96,8 @@ module.exports = function (scope, cb) { const modelName = _.get(file, 'tableName'); scope.models[modelName] = file; - if (!_.isEmpty(history) && history.hasOwnProperty(_.capitalize(modelName))) { - _.set(scope.models, modelName + '.oldAttributes', _.get(history, _.capitalize(modelName) + '.attributes')); + if (!_.isEmpty(history) && history.hasOwnProperty(modelName)) { + _.set(scope.models, modelName + '.oldAttributes', _.get(history, modelName + '.attributes')); } else { _.set(scope.models, modelName + '.oldAttributes', {}); } diff --git a/packages/strapi-generate-migrations/lib/builder/relations.js b/packages/strapi-generate-migrations/lib/builder/relations.js index 0ced321159..6791927fae 100755 --- a/packages/strapi-generate-migrations/lib/builder/relations.js +++ b/packages/strapi-generate-migrations/lib/builder/relations.js @@ -24,7 +24,7 @@ module.exports = function (models, modelName, details, attribute, toDrop, onlyDr let tplRelationUp; let tplRelationDown; - const infos = utilsModels.getNature(details, attribute, models); + const infos = toDrop ? utilsModels.getNature(details, attribute, history) : utilsModels.getNature(details, attribute, models); _.set(models[modelName].attributes, attribute + '.create', {}); _.set(models[modelName].attributes, attribute + '.delete', {}); @@ -111,21 +111,26 @@ module.exports = function (models, modelName, details, attribute, toDrop, onlyDr } else if (infos.verbose === 'belongsToMany') { // Otherwise if it's a "many-to-many" relationship. - // Save the relationship. - const relationship = models[details.collection].attributes[details.via]; + let relationship; + let relationTable; - // Construct relation table name. - const relationTable = _.map(_.sortBy([relationship, details], 'collection'), function (table) { - return _.snakeCase(pluralize.plural(table.collection) + ' ' + pluralize.plural(table.via)); - }).join('__'); + if (!onlyDrop) { + // Save the relationship. + relationship = models[details.collection].attributes[details.via]; - // Force singular foreign key. - relationship.attribute = pluralize.singular(relationship.collection); - details.attribute = pluralize.singular(details.collection); + // Construct relation table name. + relationTable = _.map(_.sortBy([relationship, details], 'collection'), function (table) { + return _.snakeCase(pluralize.plural(table.collection) + ' ' + pluralize.plural(table.via)); + }).join('__'); - // Define PK column. - details.column = utilsBookShelf.getPK(modelName, undefined, models); - relationship.column = utilsBookShelf.getPK(details.collection, undefined, models); + // Force singular foreign key. + relationship.attribute = pluralize.singular(relationship.collection); + details.attribute = pluralize.singular(details.collection); + + // Define PK column. + details.column = utilsBookShelf.getPK(modelName, undefined, models); + relationship.column = utilsBookShelf.getPK(details.collection, undefined, models); + } // Avoid to create table both times. if (!models.hasOwnProperty(relationTable) || !_.isEmpty(_.get(models, relationTable + '.up.drop'))) { @@ -191,7 +196,6 @@ module.exports = function (models, modelName, details, attribute, toDrop, onlyDr toDrop: true })); } else { - console.log("test", attribute, modelName); // Drop current relationships table on migration rollback. models[relationTable].down.drop += _.unescape(_.template(tplTableDown)({ tableName: relationTable @@ -203,7 +207,7 @@ module.exports = function (models, modelName, details, attribute, toDrop, onlyDr const tplTableDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'tables', 'dropTable.template'), 'utf8'); // Save the old relationship. - const oldRelationship = history[_.capitalize(details.collection)].attributes[details.via]; + const oldRelationship = history[details.collection].attributes[details.via]; // Construct old relation table name. const oldRelationTable = _.map(_.sortBy([oldRelationship, details], 'collection'), function (table) { @@ -212,15 +216,24 @@ module.exports = function (models, modelName, details, attribute, toDrop, onlyDr // Force singular foreign key. oldRelationship.attribute = pluralize.singular(oldRelationship.collection); + details.attribute = pluralize.singular(details.collection); // Define PK column. oldRelationship.column = utilsBookShelf.getPK(details.collection, undefined, models); + details.column = utilsBookShelf.getPK(modelName, undefined, models); - // Drop current relationships table on migration run. - models[relationTable].up.drop += _.unescape(_.template(tplTableDown)({ + + const dropMigrationTable = _.unescape(_.template(tplTableDown)({ tableName: oldRelationTable || relationTable })); + if (models[relationTable].up.drop.indexOf(dropMigrationTable) === -1) { + // Drop current relationships table on migration run. + models[relationTable].up.drop += _.unescape(_.template(tplTableDown)({ + tableName: oldRelationTable || relationTable + })); + } + // Drop current relationships table on migration rollback. // This allows us to identify, if this is an update on already existing many-to-many relationship or if this is a basic addition. if (_.isUndefined(_.get(models, relationTable + '.attributes.fk'))) { @@ -231,15 +244,15 @@ module.exports = function (models, modelName, details, attribute, toDrop, onlyDr })) } }; + } else { + // Create previous relationships table on migration rollback. + models[relationTable].down.others += _.unescape(_.template(tplTableUp)({ + models: models, + tableName: oldRelationTable || relationTable, + details: details, + relationship: oldRelationship || relationship + })); } - - // Create previous relationships table on migration rollback. - models[relationTable].down.others += _.unescape(_.template(tplTableUp)({ - models: models, - tableName: oldRelationTable || relationTable, - details: details, - relationship: oldRelationship || relationship - })); } } } diff --git a/packages/strapi-generate-migrations/templates/migration.template b/packages/strapi-generate-migrations/templates/migration.template index f8d4ed95e4..2c527e95e7 100755 --- a/packages/strapi-generate-migrations/templates/migration.template +++ b/packages/strapi-generate-migrations/templates/migration.template @@ -8,21 +8,29 @@ */ exports.up = function(connection, Promise) { - <% var dropped = false; + <% var dropped = false; var onlyDrop = true; _.forEach(models, function (definition, model) { if (!_.isEmpty(_.get(models[model], 'up.drop'))) { dropped = true; } + + if (!_.isEmpty(_.get(models[model], 'up.others'))) { + onlyDrop = false; + } }); - if (dropped) { %> return Promise.all([ + if (dropped === true && onlyDrop === false) { %> return Promise.all([ <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'up.drop') %><% }); %> ]).then(function() { return Promise.all([ <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'up.others') %><% }); %> ]); }); + <% } else if (dropped === true && onlyDrop === true) { %> + return Promise.all([ + <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'up.drop') %><% }); %> + ]); <% } else { %> return Promise.all([ <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'up.others') %><% }); %> @@ -38,17 +46,19 @@ exports.up = function(connection, Promise) { */ exports.down = function(connection, Promise) { - <% var dropped = false; + <% var dropped = false; var onlyDrop = true; _.forEach(models, function (definition, model) { if (!_.isEmpty(_.get(models[model], 'down.drop'))) { dropped = true; } + + if (!_.isEmpty(_.get(models[model], 'down.others'))) { + onlyDrop = false; + } }); - console.log("DROPPPED " + dropped); - - if (dropped) { %> + if (dropped === true && onlyDrop === false) { %> return Promise.all([ <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'down.drop') %><% }); %> ]).then(function() { @@ -56,6 +66,10 @@ exports.down = function(connection, Promise) { <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'down.others') %><% }); %> ]); }); + <% } else if (dropped === true && onlyDrop === true) { %> + return Promise.all([ + <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'down.drop') %><% }); %> + ]); <% } else { %> return Promise.all([ <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'down.others') %><% }); %> diff --git a/packages/strapi/lib/configuration/hooks/models/utils/index.js b/packages/strapi/lib/configuration/hooks/models/utils/index.js index 5d149523d5..a36ef86b9c 100755 --- a/packages/strapi/lib/configuration/hooks/models/utils/index.js +++ b/packages/strapi/lib/configuration/hooks/models/utils/index.js @@ -70,7 +70,7 @@ module.exports = { }; if (association.hasOwnProperty('via') && association.hasOwnProperty('collection')) { - const relatedAttribute = strapi.models[association.collection].attributes[association.via]; + const relatedAttribute = models[association.collection].attributes[association.via]; types.current = 'collection'; @@ -83,7 +83,7 @@ module.exports = { types.current = 'modelD'; // We have to find if they are a model linked to this key - _.forIn(strapi.models, function (model) { + _.forIn(models, function (model) { _.forIn(model.attributes, function (attribute) { if (attribute.hasOwnProperty('via') && attribute.via === key && attribute.hasOwnProperty('collection')) { types.other = 'collection'; @@ -102,7 +102,7 @@ module.exports = { types.current = 'model'; // We have to find if they are a model linked to this key - _.forIn(strapi.models, function (model) { + _.forIn(models, function (model) { _.forIn(model.attributes, function (attribute) { if (attribute.hasOwnProperty('via') && attribute.via === key) { if (attribute.hasOwnProperty('collection')) {