Ad

Why Sequelize Migration Create Table But Models Can Not Connect To A Database

I am learning how to use Sequelize ORM in Nodejs and save data in Postgres Database.

My goal is to insert user data into Users table. I have created the table using migration, and it works. However, I am not able to save users data. I 've followed many resources for example Tut 1Tut 2, etc.. , I still get the same error

C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\database\models\index.js:12
if (config.use_env_variable) {
           ^
TypeError: Cannot read property 'use_env_variable' of undefined
    at Object.<anonymous> (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\database\models\index.js:12:12)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at babelWatchLoader (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:51:13)    
    at Object.require.extensions.(anonymous function) [as .js] (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:62:7)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Module.require (internal/modules/cjs/loader.js:690:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.<anonymous> (C:\Users\HP\Desktop\Andela\project\Tutorials\react-project\chat_app_api\server\server.js:1:1)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at babelWatchLoader (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:51:13)    
    at Object.require.extensions.(anonymous function) [as .js] (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:62:7)

config/config.js

require('dotenv').config();

module.exports = {
  development: {
    use_env_variable: 'DATABASE_URL_DEV',
    dialect: 'postgres',
  },
  test: {
    use_env_variable: 'DATABASE_URL_TEST',
    dialect: 'postgres',
  },
  production: {
    use_env_variable: 'DATABASE_URL',
    dialect: 'postgres',
    ssl: true,
    dialectOptions: {
      ssl: true,
    },
  },
};

migrations/20190927083519-create-user.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        primaryKey: true,
        type: Sequelize.UUID,
        defaultValue: Sequelize.UUIDV4,
      },
      fullname: {
        type: Sequelize.STRING
      },
      email: {
        type: Sequelize.STRING
      },
      password: {
        type: Sequelize.STRING
      },
      username: {
        type: Sequelize.STRING
      },
      telephone: {
        type: Sequelize.STRING
      },
      image: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Users');
  }
};

models/index.js

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env];        // why this return Undefined ?
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

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

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

models/users

'use strict';
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    id: {
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
      primaryKey: true,
    },
    fullname: DataTypes.STRING,
    email: DataTypes.STRING,
    password: DataTypes.STRING,
    username: DataTypes.STRING,
    telephone: DataTypes.STRING,
    image: DataTypes.STRING
  }, {});
  User.associate = function (models) {
    // associations can be defined here
  };
  return User;
};

app.js

import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import bodyParser from 'body-parser';
import { errors } from 'celebrate';

import routes from './Routes/index';

const app = express();

app.use(cors());
app.use(morgan('combined'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use('/api', routes);

app.use(errors());


app.use((req, res) => {
  const error = new Error('Route not found');
  error.status = 404;
  return res.status(error.status).json({
    status: error.status,
    message: error.message,
  });
});

// Server Error
app.use((error, req, res) => {
  const status = error.status || 500;
  return res.status(status).json({
    status,
    message: error.message || 'Server error',
  });
});

export default app;

.env

DATABASE_URL_DEV=postgres://postgres:[email protected]:5432/db_dev
DATABASE_URL_TEST=postgres://postgres:[email protected]:5432/db_test
DATABASE_URL=postgres://user:[email protected]:5432/db_remote

controllers/userControllers.js

import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';

import models from '../../database/models';
import uploadImage from '../Helpers/upload.Image';

dotenv.config();

class UserController {
  static async signup(req, res) {
    const { body: input } = req;
    input.password = bcrypt.hashSync(input.password, 10);
    try {
      const image = await uploadImage(req, res);
      const { secure_url: img } = await image;

      input.image = img;
      console.log('result before ########################', models.User);         // Undefined
      const result = await models.User.create(input);
      console.log('result after ########################', result);                // Error here
      delete result.dataValues.password;

      const token = jwt.sign(result.dataValues, process.env.SECRET_KEY, { expiresIn: '1W' });
      result.dataValues.token = token;
      const status = 201;
      return res.status(status).json({
        status,
        message: 'User successfully created',
        data: result.dataValues,
      });
    } catch (error) {
      console.log('error########################', error);
      let { message } = error.errors[0];
      const status = 500;
      message = message || 'Server error';
      return res.status(status).json({
        status,
        message,
      });
    }
  }
}

export default UserController;

I still don't know why in models/index.js my config variable return undefined.

require(__dirname + '/../config/config.js')           // return object

env                                                   // return environment

const config = require(__dirname + '/../config/config.js')[env];                //return Undefined

I spent 3 days debugging but I can not solve the Error. any help, guidance is highly appreciated.

Thanks

Ad

Answer

Guyz, I found an answer to my problem,

in models/index.js

I change process.env.NODE_ENV to process.env.NODE_ENV.trim()

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);

// Before
const env = process.env.NODE_ENV || 'development';

// After
const env = process.env.NODE_ENV.trim() || 'development';    // add .trim()

const config = require(__dirname + '/../config/config.js')[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

...

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Further Details

package.json

"scripts": {
    "db:migrate:dev": "sequelize db:migrate --env development",
    "db:migrate:test": "sequelize db:migrate --env test",
    "db:migrate:production": "sequelize db:migrate --env production",
    "db:reset": "sequelize db:migrate:undo",
    "start": "SET NODE_ENV=production && babel-watch server/server.js",
    "dev": "SET NODE_ENV=development && babel-watch server/server.js",
    "test": "SET NODE_ENV=testing && babel-watch server/server.js"
  }

Example, Let's say if I start the server by typing in the terminal

npm run dev 
If i do console.log(process.env.NODE_ENV)  // output is "development " with a space.

Hence, 
 process.env.NODE_ENV === "development"  // return false
 or
 "development " === "development" // return false

Javascript Trim() remove whitespace from both sides of a string

You want more resource? please visit w3c

Ad
source: stackoverflow.com
Ad