-
Notifications
You must be signed in to change notification settings - Fork 10
모델, 마이그레이션 파일 생성하기
박지율 edited this page Jun 21, 2021
·
4 revisions
기사 모델을 생성하여 기자와 함께 살펴보기
sequelize-cli로 마이그레이션 파일을 생성하면 데이터베이스의 스키마를 변경했을 때 쉽게 이를 데이터베이스에 적용할 수 있다. 참조
그래서 아래와 같은 명령어로 간단하게 Article, Author이라는 마이그레이션 파일을 만들 수 있다.
npx sequelize-cli model:generate --name Article --attributes headline:string,author:string
npx sequelize-cli model:generate --name Author --attributes email:string,name:string,password:string
명령어를 실행하면 /models, /migrations 디렉토리에 생성한 파일이 생긴다.
생성된 testArticle, testAuthor에 현재 깃 저장소에 있는 모델과 마이그레이션 파일을 복사 붙여넣기 하면 아래와 같은 코드가 된다.
마이그레이션
# migrations/20210601013656-create-article.js
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Articles', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
headline: {
type: Sequelize.STRING,
allowNull: false,
},
category: {
type: Sequelize.INTEGER,
allowNull: false,
},
author: {
type: Sequelize.STRING,
allowNull: false,
},
image: {
type: Sequelize.STRING,
},
imageDesc: {
type: Sequelize.STRING,
allowNull: false,
},
imageFrom: {
type: Sequelize.STRING,
allowNull: false,
},
briefing: {
type: Sequelize.TEXT,
allowNull: false,
},
am7: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false,
},
pm7: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false,
},
status: {
type: Sequelize.INTEGER,
defaultValue: 1,
allowNull: false,
},
AuthorId: {
type: Sequelize.INTEGER,
allowNull: false,
onDelete: 'cascade',
references: {
model: 'Authors',
key: 'id',
},
},
publishedAt: {
allowNull: true,
type: Sequelize.DATE,
},
paragraphs: {
type: Sequelize.JSON,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Articles');
},
};
# migrations/20210601013656-create-author.js
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Authors', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
email: {
type: Sequelize.STRING,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
code: {
type: Sequelize.INTEGER,
allowNull: false,
},
position: {
type: Sequelize.INTEGER,
defaultValue: 1,
allowNull: false,
},
contact: {
type: Sequelize.STRING,
allowNull: false,
},
password: {
type: Sequelize.STRING,
allowNull: false,
},
photo: {
type: Sequelize.STRING,
allowNull: false,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Authors');
},
};
모델
# models/Article.js
const { Model } = require('sequelize');
const converter = require('../lib/converter');
const moment = require('moment');
module.exports = (sequelize, DataTypes) => {
class Article extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate({ Author }) {
this.belongsTo(Author);
// define association here
}
}
Article.init(
{
headline: {
type: DataTypes.STRING,
allowNull: false,
validate: {
len: [1, 30],
},
},
category: {
type: DataTypes.INTEGER,
allowNull: false,
get() {
return converter.category(this.getDataValue('category'));
},
},
author: {
type: DataTypes.STRING,
allowNull: false,
},
image: {
type: DataTypes.STRING,
},
imageDesc: {
type: DataTypes.STRING,
allowNull: false,
},
imageFrom: {
type: DataTypes.STRING,
allowNull: false,
},
briefing: {
type: DataTypes.TEXT,
allowNull: false,
},
am7: {
type: DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
pm7: {
type: DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
status: {
type: DataTypes.INTEGER,
defaultValue: 1,
allowNull: false,
},
publishedAt: {
allowNull: true,
type: DataTypes.DATE,
get() {
return moment(this.getDataValue('publishedAt')).format('YYYY.MM.DD HH:mm:ss');
},
},
paragraphs: {
type: DataTypes.JSON,
},
createdAt: {
allowNull: false,
type: DataTypes.DATE,
get() {
return moment(this.getDataValue('createdAt')).format('YYYY.MM.DD HH:mm:ss');
},
},
updatedAt: {
allowNull: false,
type: DataTypes.DATE,
get() {
return moment(this.getDataValue('updatedAt')).format('YYYY.MM.DD HH:mm:ss');
},
},
},
{
sequelize,
modelName: 'Article',
},
);
return Article;
};
# models/Aurhor.js
'use strict';
require('dotenv').config();
const { Model } = require('sequelize');
const authorValidator = require('./validator/authorValidator');
const bcrypt = require('bcrypt');
module.exports = (sequelize, DataTypes) => {
class Author extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate({ Article }) {
this.hasMany(Article);
}
validPassword(password) {
return bcrypt.compare(password, this.password).then((result) => result);
}
}
Author.init(
{
email: {
type: DataTypes.STRING,
allowNull: false,
unique: {
msg: '이미 존재하는 이메일입니다.',
},
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
code: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
customValidator(value) {
authorValidator.code(value);
},
},
},
position: {
type: DataTypes.INTEGER,
defaultValue: 1,
allowNull: false,
},
contact: {
type: DataTypes.STRING,
allowNull: false,
validate: {
customValidator(value) {
authorValidator.contact(value);
},
},
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: {
customValidator(value) {
authorValidator.password(value);
},
},
},
photo: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notNull: {
msg: '사진을 첨부해 주세요',
},
},
},
},
{
sequelize,
modelName: 'Author',
},
);
return Author;
};
기자가 결국 여러개의 기사를 작성할 수 있으므로 기사라는 모델은 기자와 관련성이 있습니다.
따라서 직접 코드와 같이 Author, Article model에서 static associate부분에서 두 모델의 관계를 정의할 수 있습니다.