Migration automation alpha version

This commit is contained in:
Aurélien Georget 2016-04-19 17:07:21 +02:00
parent 6d33676b9f
commit a8aa89b5e3
5 changed files with 145 additions and 75 deletions

View File

@ -23,19 +23,37 @@ module.exports = function (models, modelName) {
// Then, every `up` logic of every model call the // Then, every `up` logic of every model call the
// `./builder/tables/createTableIfNotExists` template. // `./builder/tables/createTableIfNotExists` template.
const tplTableCreate = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'tables', 'createTableIfNotExists.template'), 'utf8'); const tplTableCreate = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'tables', 'createTableIfNotExists.template'), 'utf8');
_.set(models[modelName], 'up.others', _.unescape(_.template(tplTableCreate)({ if (_.isEmpty(_.get(models[modelName], 'up.others'))) {
models: models, console.log(models[modelName]);
tableName: modelName, _.set(models[modelName], 'up.others', _.unescape(_.template(tplTableCreate)({
attributes: models[modelName].attributes, models: models,
options: models[modelName].options tableName: modelName,
}))); attributes: models[modelName].attributes,
options: models[modelName].options
})));
} else {
models[modelName].up.others += _.unescape(_.template(tplTableCreate)({
models: models,
tableName: modelName,
attributes: models[modelName].attributes,
options: models[modelName].options
}));
}
// Template: drop the table for the `down` export. // Template: drop the table for the `down` export.
// This adds a `down` logic for the current model. // This adds a `down` logic for the current model.
// Then, every `down` logic of every model call the // Then, every `down` logic of every model call the
// `./builder/tables/dropTable` template. // `./builder/tables/dropTable` template.
const tplTableDrop = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'tables', 'dropTable.template'), 'utf8'); const tplTableDrop = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'tables', 'dropTable.template'), 'utf8');
_.set(models[modelName], 'down.others', _.unescape(_.template(tplTableDrop)({
tableName: modelName if (_.isEmpty(_.get(models[modelName], 'down.others'))) {
}))); _.set(models[modelName], 'down.others', _.unescape(_.template(tplTableDrop)({
tableName: modelName
})));
} else {
models[modelName].down.others += _.unescape(_.template(tplTableDrop)({
tableName: modelName
}));
}
}; };

View File

@ -31,11 +31,10 @@ module.exports = function (rootModels, modelName, details, attribute, toDrop, on
if (!onlyDrop && toDrop) { if (!onlyDrop && toDrop) {
console.log("#1 : " + modelName);
infos = utilsModels.getNature(details, attribute, rootModels); infos = utilsModels.getNature(details, attribute, rootModels);
oldInfos = utilsModels.getNature(_.get(rootModels[modelName].oldAttributes, attribute), attribute, history); oldInfos = utilsModels.getNature(_.get(rootModels[modelName].oldAttributes, attribute), attribute, history);
const isDifferentVerbose = oldInfos.hasOwnProperty('verbose') && oldInfos.verbose === infos.verbose ? false : true; const isDifferentVerbose = oldInfos.hasOwnProperty('nature') && oldInfos.nature === infos.nature ? false : true;
if (isDifferentVerbose) { if (isDifferentVerbose) {
handleRelation(oldInfos, history, modelName, _.get(rootModels[modelName].oldAttributes, attribute), attribute, true, true); handleRelation(oldInfos, history, modelName, _.get(rootModels[modelName].oldAttributes, attribute), attribute, true, true);
@ -43,13 +42,11 @@ module.exports = function (rootModels, modelName, details, attribute, toDrop, on
} else { } else {
handleRelation(infos, rootModels, modelName, details, attribute, true, true); handleRelation(infos, rootModels, modelName, details, attribute, true, true);
} }
} else if (onlyDrop && toDrop) { } else if (onlyDrop || toDrop) {
console.log("#2 : " + modelName);
oldInfos = utilsModels.getNature(_.get(rootModels[modelName].oldAttributes, attribute), attribute, history); oldInfos = utilsModels.getNature(_.get(rootModels[modelName].oldAttributes, attribute), attribute, history);
handleRelation(oldInfos, history, modelName, _.get(rootModels[modelName].oldAttributes, attribute), attribute, true, true); handleRelation(oldInfos, history, modelName, _.get(rootModels[modelName].oldAttributes, attribute), attribute, true, true);
} else { } else {
console.log("#3 : " + modelName);
infos = utilsModels.getNature(details, attribute, rootModels); infos = utilsModels.getNature(details, attribute, rootModels);
handleRelation(infos, rootModels, modelName, details, attribute); handleRelation(infos, rootModels, modelName, details, attribute);
@ -57,8 +54,19 @@ module.exports = function (rootModels, modelName, details, attribute, toDrop, on
function handleRelation (infos, models, modelName, details, attribute, toDrop, onlyDrop) { function handleRelation (infos, models, modelName, details, attribute, toDrop, onlyDrop) {
_.set(rootModels[modelName].attributes, attribute + '.create', {}); if (_.isEmpty(_.get(rootModels[modelName].attributes, attribute + '.create'))) {
_.set(rootModels[modelName].attributes, attribute + '.delete', {}); _.set(rootModels[modelName].attributes, attribute + '.create', {
drop: '',
others: ''
});
}
if (_.isEmpty(_.get(rootModels[modelName].attributes, attribute + '.delete'))) {
_.set(rootModels[modelName].attributes, attribute + '.delete', {
drop: '',
others: ''
});
}
// If it's a "one-to-one" relationship. // If it's a "one-to-one" relationship.
if (infos.verbose === 'hasOne') { if (infos.verbose === 'hasOne') {
@ -68,26 +76,35 @@ module.exports = function (rootModels, modelName, details, attribute, toDrop, on
// Define PK column. // Define PK column.
details.column = utilsBookShelf.getPK(modelName, undefined, models); details.column = utilsBookShelf.getPK(modelName, undefined, models);
// Template: create a new column thanks to the attribute's relation. if (!toDrop) {
// Simply make a `create` template for this attribute wich will be added tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'hasOne.template'), 'utf8');
// to the table template-- either `./builder/tables/selectTable` or models[modelName].attributes[attribute].create.others += _.unescape(_.template(tplRelationUp)({
// `./builder/tables/createTableIfNotExists`. tableName: modelName,
tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'hasOne.template'), 'utf8'); attribute: attribute,
models[modelName].attributes[attribute].create.others = _.unescape(_.template(tplRelationUp)({ details: details
tableName: modelName, }));
attribute: attribute,
details: details
}));
// Template: drop the column. tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn-unique.template'), 'utf8');
// Simply make a `delete` template for this attribute wich drop the column models[modelName].attributes[attribute].delete.others += _.unescape(_.template(tplRelationDown)({
// with the `./builder/columns/dropColumn` template. tableName: modelName,
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn-unique.template'), 'utf8'); attribute: attribute,
models[modelName].attributes[attribute].delete.others = _.unescape(_.template(tplRelationDown)({ details: details
tableName: modelName, }));
attribute: attribute, } else {
details: details tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn-unique.template'), 'utf8');
})); models[modelName].attributes[attribute].create.drop += _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details
}));
tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'hasOne.template'), 'utf8');
models[modelName].attributes[attribute].delete.drop += _.unescape(_.template(tplRelationUp)({
tableName: modelName,
attribute: attribute,
details: details
}));
}
} else if (infos.verbose === 'belongsTo') { } else if (infos.verbose === 'belongsTo') {
// Force singular foreign key. // Force singular foreign key.
details.attribute = pluralize.singular(details.model); details.attribute = pluralize.singular(details.model);
@ -96,48 +113,85 @@ module.exports = function (rootModels, modelName, details, attribute, toDrop, on
details.column = utilsBookShelf.getPK(modelName, undefined, models); details.column = utilsBookShelf.getPK(modelName, undefined, models);
if (infos.nature === 'oneToMany' || infos.nature === 'oneWay') { if (infos.nature === 'oneToMany' || infos.nature === 'oneWay') {
// Template: create a new column thanks to the attribute's relation. if (!toDrop) {
// Simply make a `create` template for this attribute wich will be added tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'belongsTo.template'), 'utf8');
// to the table template-- either `./builder/tables/selectTable` or rootModels[modelName].attributes[attribute].create.others += _.unescape(_.template(tplRelationUp)({
// `./builder/tables/createTableIfNotExists`. tableName: modelName,
attribute: attribute,
details: details,
nature: infos.nature
}));
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn.template'), 'utf8');
rootModels[modelName].attributes[attribute].delete.drop += _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details
}));
} else {
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropForeign.template'), 'utf8');
rootModels[modelName].attributes[attribute].create.drop += _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details,
}));
tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'belongsTo.template'), 'utf8');
rootModels[modelName].attributes[attribute].delete.others += _.unescape(_.template(tplRelationUp)({
tableName: modelName,
attribute: attribute,
details: details,
nature: infos.nature
}));
}
} else {
if (!toDrop) {
tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'belongsTo-unique.template'), 'utf8');
rootModels[modelName].attributes[attribute].create.others += _.unescape(_.template(tplRelationUp)({
tableName: modelName,
attribute: attribute,
details: details
}));
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn-unique.template'), 'utf8');
rootModels[modelName].attributes[attribute].delete.drop += _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details
}));
} else {
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn.template'), 'utf8');
rootModels[modelName].attributes[attribute].create.drop += _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details,
}));
tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'belongsTo.template'), 'utf8');
rootModels[modelName].attributes[attribute].delete.others += _.unescape(_.template(tplRelationUp)({
tableName: modelName,
attribute: attribute,
details: details,
nature: infos.nature
}));
}
}
} else if (infos.verbose === 'hasMany') {
if (toDrop) {
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropForeign.template'), 'utf8');
rootModels[modelName].attributes[attribute].create.drop += _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details,
}));
tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'belongsTo.template'), 'utf8'); tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'belongsTo.template'), 'utf8');
rootModels[modelName].attributes[attribute].create.others = _.unescape(_.template(tplRelationUp)({ rootModels[modelName].attributes[attribute].delete.others += _.unescape(_.template(tplRelationUp)({
tableName: modelName, tableName: modelName,
attribute: attribute, attribute: attribute,
details: details, details: details,
nature: infos.nature nature: infos.nature
})); }));
// Template: drop the column.
// Simply make a `delete` template for this attribute wich drop the column
// with the `./builder/columns/dropColumn` template.
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn.template'), 'utf8');
rootModels[modelName].attributes[attribute].delete.drop = _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details
}));
} else {
// Template: create a new column thanks to the attribute's relation.
// Simply make a `create` template for this attribute wich will be added
// to the table template-- either `./builder/tables/selectTable` or
// `./builder/tables/createTableIfNotExists`.
tplRelationUp = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'relations', 'belongsTo-unique.template'), 'utf8');
rootModels[modelName].attributes[attribute].create.others = _.unescape(_.template(tplRelationUp)({
tableName: modelName,
attribute: attribute,
details: details
}));
// Template: drop the column.
// Simply make a `delete` template for this attribute wich drop the column
// with the `./builder/columns/dropColumn` template.
tplRelationDown = fs.readFileSync(path.resolve(__dirname, '..', '..', 'templates', 'builder', 'columns', 'dropColumn-unique.template'), 'utf8');
rootModels[modelName].attributes[attribute].delete.drop = _.unescape(_.template(tplRelationDown)({
tableName: modelName,
attribute: attribute,
details: details
}));
} }
} else if (infos.verbose === 'belongsToMany') { } else if (infos.verbose === 'belongsToMany') {
// Otherwise if it's a "many-to-many" relationship. // Otherwise if it's a "many-to-many" relationship.

View File

@ -1,3 +1,3 @@
// Delete the `<%= attribute %>` column with unique constraint. // Delete the `<%= attribute %>` column with unique constraint.
table.dropUnique('<%= attribute %>').dropColumn('<%= attribute %>') table.dropUnique('<%= tableName.toLowerCase() %>_<%= attribute %>_unique').dropColumn('<%= attribute %>')

View File

@ -1,3 +1,3 @@
// Delete the foreign key on `<%= attribute %>` column. // Delete the foreign key on `<%= attribute %>` column.
table.dropForeign('<%= attribute %>') table.dropForeign('<%= attribute %>').dropColumn('<%= attribute %>')

View File

@ -58,8 +58,6 @@ exports.down = function(connection, Promise) {
} }
}); });
console.log("MIGRATION: " + dropped, onlyDrop);
if (dropped === true && onlyDrop === false) { %> if (dropped === true && onlyDrop === false) { %>
return Promise.all([ return Promise.all([
<% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'down.drop') %><% }); %> <% _.forEach(models, function(definition, model) { %><%= _.get(models[model], 'down.drop') %><% }); %>