Sequelize with express - javascript

I'm following a tutorial which uses sequelize with an express project. Here's the user.js model:
// in models/User.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('User', {
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
}, {
instanceMethods: {
countTasks: function() {
// how to implement this method ?
}
}
});
};
Then he uses User in various of ways, for example:
var user = User.build({ first_name: 'John', last_name: 'Doe' });
I understand the code in general, but I don't understand completely why module.exports gets a function with two parameters (sequelize, DataTypes). I haven't seen it initialized anywhere in the code. How is it working then?

If you are following this guide you will see in models/index.js that all model definitions are looped through and passed to seqelize.import().
You will find that this line of code within sequelize.import calls the model's module function and passes a reference to sequelize and DataTypes to the model.
In the tutorial you referenced, the author uses a similar method within models/index.js
> Edit (7/14/2015)
Since the link does not work and I could not find it on their current site, I copied the code from their site using The Wayback Machine. I also updated the second link to point to the 2.0 docs instead of master.
models/index.js
"use strict";
var fs = require("fs");
var path = require("path");
var Sequelize = require("sequelize");
var env = process.env.NODE_ENV || "development";
var config = require(__dirname + '/../config/config.json')[env];
var sequelize = new Sequelize(config.database, config.username, config.password, config);
var db = {};
fs
.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf(".") !== 0) && (file !== "index.js");
})
.forEach(function(file) {
var model = sequelize["import"](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ("associate" in db[modelName]) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;

Related

getting empty response on sequelize findall from postgres

I am new to node js environment and currently I am practicing a crud applicaiton
I am using sequelize as ORM and I have used the mvc structure
npm install --save sequelize
$ npm install --save pg pg-hstore
I am using sequelize cli
npm install --save-dev sequelize-cli
npx sequelize-cli init
It is my migration
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Books', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
firstName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Books');
}
};
My Model:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Books 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(models) {
// define association here
}
};
Books.init({
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
email: DataTypes.STRING
}, {
sequelize,
modelName: 'Books',
});
return Books;
};
MY Controller:
exports.allBooks = (req,res)=>{
const bookme = Books(**how to pass sequelize**,**how to pass sequelize datatype**)
var booksJSON = bookme.findAll()
res.json(booksJSON)
console.log(JSON.stringify(booksJSON))
}
I am getting the empty response if I pass the datatypes customly by creating a connection manually to database with sequelize and passing that sequelize to the books models
I think that my mistake is in passing these parameters. What and how shoudld I pass to the Books model
I am importing the books model as follows in my controller:
const Books = require('../models/books.js');
also when i ran the bootstraping that created migrations,models,seeding folders it also created a index.js file in models folder
I have tried passing that too in the parameter to Books model but It gave error
index.js in models folder created by sequelize cli package itself
'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.json')[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);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
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;
The error I got when I try to pass this db from index.js to Books model in my controller is:
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
^
TypeError: Class constructor model cannot be invoked without 'new'
What should I pass to the parameter and from where?
I am getting response by using aysnc and await. I used second parameter by importing directly from the package
const Sequelize = require('sequelize')
and for first parameter I used the manually created connection.
but it still doesn't clears my concern of actually what parameters were to pass

Sequelize Create/Import Dynamically Generated Models

I have a Sequelize migration script (built off sequelize-cli's initial migration script generated from running sequelize-cli) that dynamically creates tables based on a list of ~100 hardcoded table names imported from a .json file. Thus, it will be tedious and error-prone to hardcode the Sequelize model definitions by hand.
Question: How can we dynamically generate the Sequelize models by reading from the same .json file? I am mainly stuck how we should return multiple Sequelize models using module.exports, based on the model definition file auto-generated from running sequelize-cli model:generate --name Base .... There appears to be a special script models/index.js for reading the model definition file models/base.js.
models/base.js
'use strict';
const universe = require('../config/universe.json');
const generateModel = (sequelize, DataTypes, tableName) => {
const schema = {
name: DataTypes.STRING,
power: DataTypes.DOUBLE,
};
const options = {
timestamps: false,
};
const Model = sequelize.define(tableName, schema, options);
Model.associate = function(models) {
// associations can be defined here
}
return Model;
}
module.exports = (sequelize, DataTypes) => {
models = []
for (let planet in universe) {
for (const species of universe[planet]) {
models.push(generateModel(species));
}
}
return models;
};
app.js
Attempting to load the dynamically created model Human
const Human = require('./models').base.human;
Human.create({name: 'Tom', power: 1.23});
config/universe.json
Example hardcoded data file
{
"earth": [
'human',
'cat',
'dog'
]
}
models/index.js
This file is auto-generated after running sequelize-cli init
'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.json')[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);
}
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;

Sequelize ORM: How to statically associate models to db?

I'm using sequelize on my ReactJS application to access my database. Follow the tutorial, below is my sequelize initializer used to load all models and make then available to db:
"use strict";
var fs = require("fs");
var path = require("path");
var Sequelize = require("sequelize");
var basename = path.basename(__filename);
var env = process.env.NODE_ENV || "development";
var config = require(__dirname + "/../config/config.js")[env];
var db = {};
if (config.use_env_variable) {
var sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
var 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 => {
var 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;
This is how a simple model looks like: TestModel.js
export default (sequelize, DataTypes) => {
let TestModel = sequelize.define("TestModel", {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
name: { type: DataTypes.STRING(32), allowNull: false },
description: { type: DataTypes.STRING(256) }
});
return TestModel;
};
And then I can normally use it inside my code:
db.TestModel.find(...);
All running fine, until I need to prepare the production bundle.
I'm using webpack to prepare the production bundle that is delivered as a single file. When doing so, the model files are not any more available for importing at:
fs
.readdirSync(__dirname)
.filter(file => {
return (
file.indexOf(".") !== 0 &&
file !== basename &&
file.slice(-3) === ".js"
);
})
.forEach(file => {
var model = sequelize["import"](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
.. and then there are no more models available to be used from db, what causes my database access code db.TestModel.find(...); to fail with the following error: TypeError: Cannot read property 'find' of undefined
Naturally no files were imported (there is just my bundle.js) and db does not contain the model definition.
So, I need a way to statically import the models, and here is my try:
import TestModel from "./TestModel.js";
.
.
.
db[TestModel.name].associate(db);
Althought this runs, it does not associate and I'm getting the same error at runtime.
How can I statically associate my models to sequelize db so that I can access then directy as db.ModelName ?

Sequelize & Express model & associate setup

Background
I am working with Sequelize v4.2 and Express v4.15.2 and attempting to setup the models and associate them with one another. I have struggled to find any working v4.x Sequelize examples even after viewing this Express/Sequelize tutorial as well as the v4 migration docs.
Issue
Currently I am receiving the error below when trying to setup my initial models and associations.
/Users/james/Sites/awesome-app/server/node_modules/sequelize/lib/associations/mixin.js:80
if (!target.prototype || !(target.prototype instanceof this.sequelize.Model)) {
TypeError: Cannot read property 'prototype' of undefined
at Function.<anonymous> (/Users/james/Sites/awesome-app/server/node_modules/sequelize/lib/associations/mixin.js:80:16)
Files/Code
My model setup file (index.js) looks like...
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
let db = {};
let sequelize = undefined;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter((file) => {
return (file.indexOf(".") !== 0) && (file !== 'index.js');
})
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ('associate' in db[modelName]) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
And my first model (address.js) that fails looks like...
module.exports = function(sequelize, DataTypes) {
var Address = sequelize.define('Address', {
street: DataTypes.STRING,
city: DataTypes.STRING,
state: DataTypes.STRING,
zip: DataTypes.STRING,
});
Address.associate = function(models) {
Address.belongsTo(models.attendeeGroup, {
onDelete: 'CASCADE',
foreignKey: {
allowNull: false
},
});
}
return Address;
};
I am looking to setup my database tables and associate various models with one another. Is there another piece of setup I am missing?
My model I wanted to associate with was incorrectly named/capitalized. I had Address.belongsTo(models.attendeeGroup, { where attendeeGroup was camel case, but in fact it needed to be capitalized like AttendeeGroup which is the name of my other model.
My database was successfully created once I changed this model name.

sequelize is not defined - Sequelize and consign

I'm new in node.
I'm trying to add Sequelize in my simple application with cosign.
config/db.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize('test', 'root', '', {
host: 'localhost',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
idle: 10000
}
});
module.exports = function () {
return sequelize
}
model/user.js
var Sequelize = require('sequelize');
module.exports = function(application, req, res){
var User = sequelize.define('user', {
username: {
type: Sequelize.STRING,
}
}, {
freezeTableName: true // Model tableName will be the same as the model name
});
User.create({ username: 'fnord'})
.then(function() {
console.log('criado!');
})
}
config/server.js
...
consign()
.include('app/routes')
.then('config/db.js')
.then('app/models')
.then('app/controllers')
.into(app);
module.exports = app;
I'm getting the error sequelize is not definedĀ“ onvar User = sequelize.define('user', {`
What I'm doing wrong?
Create an index.js file inside your moldes folder like this:
"use strict";
var fs = require("fs");
var path = require("path");
var Sequelize = require("sequelize");
var sequelize = new Sequelize(global.config.dbConfig.name, global.config.dbConfig.user, global.config.dbConfig.password, {
host: global.config.dbConfig.host,
port: global.config.dbConfig.port,
pool: false
});
var db = {};
fs.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf(".") !== 0) && (file !== "index.js");
})
.forEach(function(file) {
var model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ("associate" in db[modelName]) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
module.exports = db;
and in your user.js do something like this:
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: {
type: DataTypes.STRING
},
{
freezeTableName: true // Model tableName will be the same as the model name
}
});
return User;
}
http://docs.sequelizejs.com/en/1.7.0/articles/express/
You should require sequelize instance into user model
config/db.js
module.exports = sequelize;
model/user.js
var Sequelize = require('sequelize');
var sequelize = require('../config/db.js'); //sequelize instance
module.exports = function(application, req, res){
var User = sequelize.define('user', {
...
The Sequelize-CLI is a very useful tool for projects that use Sequelize. When you download it
npm install -g sequelize-cli
You can then run
sequelize init
The above command will go and write out a few folders for you including a models folder that has the index file that Ricardo created above. This gives some really cool environment configuration as well. Within the new models folder, you can create a new file with your object with the syntax...
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: {
type: DataTypes.STRING
},
{
freezeTableName: true // Model tableName will be the same as the model name
}
});
return User;
}
While I do like this as a tool. It is key here to notice that Sequelize will go and look for the first argument to the define() method. So we could just write
module.exports = function(sequelize, DataType){
return sequelize.define("User", {
username: {
type: DataTypes.STRING
},
{
freezeTableName: true // Model tableName will be the same as the model name
}
});

Categories