React-starter-kit: How to use Sequelize Migrations with RSK?

Created on 15 Mar 2018  Â·  5Comments  Â·  Source: kriasoft/react-starter-kit

Do you use Sequelize migrations? If so, would you share how you do it?

not directly related

Most helpful comment

hello, i made the following:

you have to add to your .babelrc the wildcard plugin
yarn add --dev babel-plugin-wildcard
then add to .babelrc plugins: ['wildcard']

// src/data/models/index.js
import db from '../sequelize';
import * as models from './*';

delete models.Index; // remove the index (we dont want to include myself again)

Object.keys(models).forEach((modelName) => {
  db[modelName] = models[modelName](db.sequelize, db.Sequelize);
});

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

export default db;

```js
// src/data/sequelize.js
import Sequelize from 'sequelize';
import config from './config/config';

const db = config[process.env.NODE_ENV || 'development'];

const sequelize = new Sequelize(db.database, db.username, db.password, {
host: db.host,
port: db.port,
dialect: db.dialect,
dialectOptions: db.dialectOptions,
ssl: db.ssl,
define: {
freezeTableName: true,
},
native: false,
logging: console.log,
});

const database = {};

database.sequelize = sequelize;
database.Sequelize = Sequelize;
export default database;

```js
// src/data/config/config.js
// im forcing some configs but u can import your original ./config.js and use it as u want
const env = process.env.NODE_ENV || 'development';

export default {
  [env]: {
    username: "postgres",
    password: "postgres",
    database: "postgres",
    host: "localhost",
    port: "32773",
    dialect: "postgres",
    ssl: false,
    dialectOptions: {
      ssl: false,
    },
  },
};

then at the root of your project add .sequelizerc file with:

const path = require('path');

module.exports = {
  'config': path.resolve('src', 'data', 'config', 'config.js'),
  'migrations-path': path.resolve('src', 'data', 'migrations'),
  'seeders-path': path.resolve('src', 'data', 'seeders'),
  'models-path': path.resolve('src', 'data', 'models'),
};

model example:
(still using sequelize v3, u might want to check the migration guide to v4 if using)

// src/data/models/User.js
/* eslint-disable camelcase */
import bcrypt from 'bcryptjs';
// import md5 from 'crypto-js/md5';

export default (sequelize, DataType) =>
  sequelize.define('users', {
    id: {
      type: DataType.UUID,
      defaultValue: DataType.UUIDV4,
      primaryKey: true,
    },
    email: {
      type: DataType.STRING,
      allowNull: false,
      validate: {
        isEmail: {
          args: true,
          msg: 'Email format is wrong',
        },
      },
      unique: {
        args: true,
        msg: 'Email address already in use!',
      },
    },
    password: {
      type: DataType.STRING(255),
      allowNull: false,
    },
    first_name: {
      type: DataType.STRING(40),
      allowNull: true,
    },
    last_name: {
      type: DataType.STRING(40),
      allowNull: true,
    },
    last_login: {
      type: DataType.DATE,
      default: sequelize.NOW,
    },
  }, {
    schema: 'public',
    underscored: true,
    classMethods: {
      generateHash(password) {
        return bcrypt.hashSync(password, bcrypt.genSaltSync(12), null);
      },
      associate({ User, UserRole, MediaLibrary, ChatMessage, TeamMember }) {
        // user belongs to a role
        User.belongsTo(UserRole, {
          foreignKey: 'role_id',
          as: 'Role',
        });
        User.belongsTo(MediaLibrary, {
          foreignKey: 'media_id',
          as: 'Avatar',
        });
        // a user can have many messages
        User.hasMany(ChatMessage, {
          as: 'Messages',
          foreignKey: 'message_id',
        });
        User.hasOne(TeamMember);
      },
    },
    instanceMethods: {
      comparePassword(password) {
        return bcrypt.compareSync(password, this.password);
      },
    },
  });

create a script on package.json to load sequelize cli using babel

"scripts": {
...
    "sequelize": "babel-node ./node_modules/.bin/sequelize $*"
...
}

then you can do

yarn sequelize db:migrate

hope it works for you.
also im not calling sync() on server.js

edit:
i forgot,
also i add to webpack config exclude for seeds folder and migrations,

All 5 comments

hello, i made the following:

you have to add to your .babelrc the wildcard plugin
yarn add --dev babel-plugin-wildcard
then add to .babelrc plugins: ['wildcard']

// src/data/models/index.js
import db from '../sequelize';
import * as models from './*';

delete models.Index; // remove the index (we dont want to include myself again)

Object.keys(models).forEach((modelName) => {
  db[modelName] = models[modelName](db.sequelize, db.Sequelize);
});

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

export default db;

```js
// src/data/sequelize.js
import Sequelize from 'sequelize';
import config from './config/config';

const db = config[process.env.NODE_ENV || 'development'];

const sequelize = new Sequelize(db.database, db.username, db.password, {
host: db.host,
port: db.port,
dialect: db.dialect,
dialectOptions: db.dialectOptions,
ssl: db.ssl,
define: {
freezeTableName: true,
},
native: false,
logging: console.log,
});

const database = {};

database.sequelize = sequelize;
database.Sequelize = Sequelize;
export default database;

```js
// src/data/config/config.js
// im forcing some configs but u can import your original ./config.js and use it as u want
const env = process.env.NODE_ENV || 'development';

export default {
  [env]: {
    username: "postgres",
    password: "postgres",
    database: "postgres",
    host: "localhost",
    port: "32773",
    dialect: "postgres",
    ssl: false,
    dialectOptions: {
      ssl: false,
    },
  },
};

then at the root of your project add .sequelizerc file with:

const path = require('path');

module.exports = {
  'config': path.resolve('src', 'data', 'config', 'config.js'),
  'migrations-path': path.resolve('src', 'data', 'migrations'),
  'seeders-path': path.resolve('src', 'data', 'seeders'),
  'models-path': path.resolve('src', 'data', 'models'),
};

model example:
(still using sequelize v3, u might want to check the migration guide to v4 if using)

// src/data/models/User.js
/* eslint-disable camelcase */
import bcrypt from 'bcryptjs';
// import md5 from 'crypto-js/md5';

export default (sequelize, DataType) =>
  sequelize.define('users', {
    id: {
      type: DataType.UUID,
      defaultValue: DataType.UUIDV4,
      primaryKey: true,
    },
    email: {
      type: DataType.STRING,
      allowNull: false,
      validate: {
        isEmail: {
          args: true,
          msg: 'Email format is wrong',
        },
      },
      unique: {
        args: true,
        msg: 'Email address already in use!',
      },
    },
    password: {
      type: DataType.STRING(255),
      allowNull: false,
    },
    first_name: {
      type: DataType.STRING(40),
      allowNull: true,
    },
    last_name: {
      type: DataType.STRING(40),
      allowNull: true,
    },
    last_login: {
      type: DataType.DATE,
      default: sequelize.NOW,
    },
  }, {
    schema: 'public',
    underscored: true,
    classMethods: {
      generateHash(password) {
        return bcrypt.hashSync(password, bcrypt.genSaltSync(12), null);
      },
      associate({ User, UserRole, MediaLibrary, ChatMessage, TeamMember }) {
        // user belongs to a role
        User.belongsTo(UserRole, {
          foreignKey: 'role_id',
          as: 'Role',
        });
        User.belongsTo(MediaLibrary, {
          foreignKey: 'media_id',
          as: 'Avatar',
        });
        // a user can have many messages
        User.hasMany(ChatMessage, {
          as: 'Messages',
          foreignKey: 'message_id',
        });
        User.hasOne(TeamMember);
      },
    },
    instanceMethods: {
      comparePassword(password) {
        return bcrypt.compareSync(password, this.password);
      },
    },
  });

create a script on package.json to load sequelize cli using babel

"scripts": {
...
    "sequelize": "babel-node ./node_modules/.bin/sequelize $*"
...
}

then you can do

yarn sequelize db:migrate

hope it works for you.
also im not calling sync() on server.js

edit:
i forgot,
also i add to webpack config exclude for seeds folder and migrations,

THANK YOU so much for this. Was able to finally get everything working with the thorough writeup. Much appreciated! @langpavel

@ericchen0121 I think you should thanks to @ricardomoura. I'm only edited answer by specifying syntax highlighting hinting ``` → ```js in markdown :-)

@ricardomoura thanks a lot, that's well written examples, one more question for you,
when using sequelize cli to generate the model, the name is singular but after migrating, it's "plural" in db, i know this is the default behavior of sequelize, but the problem is when i do db.user.findAll(), the query printed in terminal is looking for user instead of users, though user does not exist, i saw in your src/data/models/User.js file, you have users, not user, are you changing this yourself? i thought sequelize should be smart enough to deal with this situation.

sorry was on vacations. the first argument of sequelize.define is the table name not sure if i get what you mean. maybe the sequelize cli tool is generating by default singular table names. check on your migration file @warm200

Was this page helpful?
0 / 5 - 0 ratings