Sequelize N:M ParentModel.setChilds(ChildArray) is not a function (Magic Method?) - mysql

In my program, I'd like to update many cateogories has a parent table named Column. Also, a category can contain of many columns.(N:M)
So I tried to update a category to the post, but it failed. Here is the code I've tried
let updateColumn = async function(req, res) {
let column_id = req.body.id;
let column_title = req.body.title;
let column_content_text = req.body.contentText;
let column_content_html = req.body.contentHTML;
let column_categorys = req.body.categoris;
let column_tags = req.body.tags;
let column_thumbnail_url = process.env.CDN_COLUMN_ENDPOINT;
column_thumbnail_url += column_title;
column_thumbnail_url += '/';
column_thumbnail_url += '0.png';
var category_array = [];
var tag_array = [];
await sequelize.transaction(async transaction => {
try {
await Column.update({
column_title: column_title,
column_content_text: column_content_text,
column_content_html: column_content_html,
column_thumbnail_url: column_thumbnail_url,
}, {
where: {
id: column_id,
},
}, {transaction: transaction});
const column = await Column.findOne({
where: {
id: column_id,
},
transaction,
});
for(var i in column_categorys) {
const [category, created] = await Category.findOrCreate({
where : {
category_name: column_categorys[i],
},
transaction,
});
category_array.push(category);
}
for(var j in column_tags) {
const [tag, created] = await Tag.findOrCreate({
where : {
tag_name: column_tags[j],
},
transaction,
});
tag_array.push(tag);
}
await column.setCategorys(
category_array,
{ transaction },
);
await column.setTags(
tag_array,
{ transaction },
);
res.json({
responseCode: 400,
responseMsg: 'Success',
});
} catch (err) {
console.error(err);
res.json({
responseCode: 404,
responseMsg: 'Fail',
});
}
});
}
column_info.js
const Sequelize = require('sequelize');
module.exports = class Column extends Sequelize.Model {
static init(sequelize) {
return super.init({
column_title: {
type: Sequelize.STRING(200),
allowNull: false,
unique: true,
},
column_content_text: {
type: Sequelize.STRING(10000),
allowNull: false,
},
column_content_html: {
type: Sequelize.STRING(10000),
},
column_thumbnail_url: {
type: Sequelize.STRING(300),
},
}, {
sequelize,
timestamps: true,
underscored: true,
modelName: 'Column',
tableName: 'columns',
paranoid: true,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.Column.belongsToMany(db.Category, {
through: 'ColumnCategory',
unique: false,
});
db.Column.belongsToMany(db.Tag, {
through: 'ColumnTag',
unique: false,
});
}
};
category_info.js
const Sequelize = require('sequelize');
module.exports = class Category extends Sequelize.Model {
static init(sequelize) {
return super.init({
category_name: {
type: Sequelize.STRING(50),
allowNull: false,
unique: true,
},
}, {
sequelize,
timestamps: false,
underscored: true,
modelName: 'Category',
tableName: 'categorys',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.Category.belongsToMany(db.Column, {
through: 'ColumnCategory',
unique: false,
});
}
};
model/index.js
const Sequelize = require('sequelize');
const User = require('./user');
const Baby = require('./baby_info');
const UserCase = require('./user_case');
const Column = require('./column_info');
const Tag = require('./tag_info');
const Category = require('./category_info');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.User = User;
db.Baby = Baby;
db.UserCase = UserCase;
db.Column = Column;
db.Tag = Tag;
db.Category = Category;
User.init(sequelize);
Baby.init(sequelize);
UserCase.init(sequelize);
Column.init(sequelize);
Tag.init(sequelize);
Category.init(sequelize);
User.associate(db);
Baby.associate(db);
UserCase.associate(db);
Column.associate(db);
Tag.associate(db);
Category.associate(db);
module.exports = db;
error log
0|app | 21-01-04 16:09:26: TypeError: column.setCategorys is not a function
0|app | 21-01-04 16:09:26: at /home/ubuntu/bebenity/routes/column/column.ctrl.js:66:20
0|app | 21-01-04 16:09:26: at processTicksAndRejections (internal/process/task_queues.js:93:5)
0|app | 21-01-04 16:09:26: at async /home/ubuntu/bebenity/node_modules/sequelize/lib/sequelize.js:1090:24
0|app | 21-01-04 16:09:26: at async updateColumn (/home/ubuntu/bebenity/routes/column/column.ctrl.js:21:3)
Could you tell me what part of this code I've used relationship queries incorrectly?
Add 1
Actually, I've had a similar experience.
How to add child row in related table?? (Sequelzie N:M Relationship)
In that example, the method findOrCreate's callback value has a problem.
But, in this question, the method findOne's callback value is clearly Model Object! I have already checked through column instanceof Column that the column is the Column model instance.(It is true)
But it is a little bit different between model with Create method and findOne
Create Callback
findOne Callback

The solution was very simple...
Revising my column.setCategorys to column.setCategories was that...
OMG

Related

TypeError: Cannot read properties of undefined (reading 'findOne')

Hello i have problem with creating role in my db. The error is TypeError: Cannot read properties of undefined (reading 'findOne')
role model:
const {sequelize, DataTypes} = require('sequelize')
module.exports = (sequelize, DataTypes) => {
const role = sequelize.define("role",{
roleTitle: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.TINYINT,
allowNull: false
},
status: {
type: DataTypes.BOOLEAN,
allowNull: false
},
}
)
return role
}
add role func:
const db= require('../models')
const Role = db.roles
const addRole = async (req, res) => {
let info = {
roleTitle : req.query.roleTitle,
description : req.query.description,
status : req.query.status
}
const exrole = await Role.findOne({ where: { roleTitle : 'title' }})
// if(exuser == null){
const role = await Role.create({
roleTitle : "okkk",
description : 'info.description',
status : false
}
)
res.status(200).send(user)
console.log(user)
// }else{
// res.status(404).send({erorr : '404'})
}
module.exports = {
addRole
}
You return role and try to access db.roles. Change to db.role and it should pass this error

how to store logs into mysql db using express-winston in Node.js

I am trying to store logs into mysql db(with Sequelize) using express-winston in Node.js.
According to doc(https://www.npmjs.com/package/winston-sql-transport), I should do the following:
const { Logger } = require('winston');
const { SQLTransport } = require('./../lib/winston-sql-transport');
const logger = new Logger({
transports: [
new SQLTransport({
tableName: 'winston_logs',
})]
});
module.exports = logger;
I apply above code in app.js, but not successful.
app.js
const { SQLTransport } = require('./../lib/winston-sql-transport'); // //Error: Cannot find module './../lib/winston-sql-transport'
const mysqlOption = {
tableName: 'winston_logs'
}
app.use(
expressWinston.logger({
transports: [
new SQLTransport(mysqlOption)
],
format: winston.format.combine(
winston.format.timestamp({ format: timezoned }),
winston.format.json(),
),
metaField: null,
expressFormat: true,
statusLevels: false,
level: function (req, res) {
var level = "";
if (res.statusCode < 400) { level = "info"; }
if (res.statusCode >= 400) { level = "warn"; }
if (res.statusCode >= 500) { level = "error"; }
return level;
}
})
)
I tried to change the import to const { SQLTransport } = require('winston-sql-transport');
Resulting error:
Error: You have to define client
at new SQLTransport (/server/node_modules/winston-sql-transport/lib/winston-sql-transport.js:40:13)
I found that people rarely talk about this package.
So I wonder if there is any way to do it?
Update 1:
I updated mysqlOption as suggested by the comment
const { SQLTransport } = require('winston-sql-transport');
const mysqlOption = {
tableName : "winston_logs",
client: 'mysql',
connection: {
host: '127.0.0.1:3306',
user: 'root',
password: '',
database: 'mydb'
}
}
The logs successfully appear in Console, but nothing store in my database.
Update 2:
Since I am using Sequelize, I'm going to provide the schema for the logs table
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const logs = sequelizeClient.define('winston_logs', {
id: {
type: DataTypes.INTEGER(10),
allowNull: false,
autoIncrement: true,
primaryKey: true
},
level: {
type: DataTypes.STRING(45),
allowNull: false
},
message: {
type: DataTypes.TEXT,
allowNull: false
},
meta: {
type: DataTypes.STRING(255),
allowNull: false
},
hostname: {
type: DataTypes.STRING(255),
allowNull: false
},
timestamp: {
type: DataTypes.DATE,
allowNull: false
},
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
logs.associate = function (models) {
};
return logs;
};
Finally giving up to store logs in mysql db, since mysql transport package seems a bit outdated.
Instead, I store the logs locally, using winston-daily-rotate-file
It can set the frequency of rotation, Maximum size of the file etc.
link: https://github.com/winstonjs/winston-daily-rotate-file

Sequelize: refer a foreign key between 2 models

I'm trying to refer a foreign key between 2 models. but I'm getting this error:
throw new AssociationError(`${source.name}.belongsToMany(${target.name}) requires through option, pass either a string or a model`);
AssociationError [SequelizeAssociationError]: Order.belongsToMany(User) requires through option, pass either a string or a model
I check some similar questions but it didn't help.
I started working with Sequelize today so please give an example to answer.
db.js
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const basename = path.basename(module.filename);
const db = {};
const sequelize = new Sequelize("name", "user", "password", {
host: "localhost",
dialect: "mysql",
logging: false,
});
fs.readdirSync(__dirname).filter(file =>
(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;
user.js
const Sequelize = require("sequelize");
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define("User",
{
id: {
type: Sequelize.BIGINT,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
email: Sequelize.STRING(60),
password: Sequelize.STRING(60),
fullName: {
type: Sequelize.STRING(60),
allowNull: true,
},
},
);
User.associate = function (models) {
models.User.belongsToMany(models.Order);
};
return User;
};
order.js
const Sequelize = require("sequelize");
module.exports = (sequelize, DataTypes) => {
const Order = sequelize.define("Order",
{
id: {
type: Sequelize.BIGINT,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
title: Sequelize.STRING(60),
orderNumber: Sequelize.STRING(60),
status: Sequelize.STRING(60),
amount: Sequelize.STRING(60),
trackingCode: Sequelize.STRING(60),
},
);
Order.associate = function(models) {
models.Order.belongsToMany(models.User);
};
return Order;
};
when I use lowercase for define name like this:
const User = sequelize.define("user",
{
...
}
);
const User = sequelize.define("order",
{
...
}
);
I get this error:
TypeError: Cannot read property 'belongsToMany' of undefined
sequelize: 5.21.6
I answered similar question here. Please take a look at it. Also pay attention to comments and to the link at the end of the discussion.
If you'll have any questions after reading feel free to ask them in comments to this answer.

How to add associations to Models generated from Sequelize-Auto

For an existing MySQL database, I used Sequelize-auto package to generate the models. But the associations don't come with model classes.
I have an MySQL database and I'm using it for NodeJS web project. Also I'm using Sequelize as the ORM. Since database is already there I wanted to generate the model classes as the entities. So I used sequelize-auto
https://github.com/sequelize/sequelize-auto to generate the model classes. But when they were generated attributes have been correctly set but the associations doesn't come up with the model classes. So I have faced problem when fetching the data from the database.
Here are the two model classes that were generated with sequlize-auto. There are two table in the database named as department and category. department.js and category.js are the two model classes that were generated
department.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('department', {
department_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(100),
allowNull: false
},
description: {
type: DataTypes.STRING(1000),
allowNull: true
}
}, {
tableName: 'department',
timestamps: false,
});
};
category.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('category', {
category_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
department_id: {
type: DataTypes.INTEGER(11),
allowNull: false
},
name: {
type: DataTypes.STRING(100),
allowNull: false
},
description: {
type: DataTypes.STRING(1000),
allowNull: true
}
}, {
tableName: 'category',
timestamps: false,
});
};
So what else needs to be done in order to get the associations and to fetch data successfully. Can some one help me here. Table structure is as following.
1) inside of your models folder create an index.js file and add the following code
import Sequelize from 'sequelize';
const fs = require('fs');
const path = require('path');
const basename = path.basename(__filename);
const db = {};
// #ts-ignore
const sequelize = new Sequelize('dbname', 'dbUser', 'password', {
host: '127.0.0.1',
port: 'PORT',
dialect: 'mysql',
define: {
freezeTableName: true,
timestamps: false,
},
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
},
// <http://docs.sequelizejs.com/manual/tutorial/querying.html#operators>
operatorsAliases: false,
});
const tableModel = {};
fs.readdirSync(__dirname)
.filter(file => file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js')
.forEach(file => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
tableModel[model.name] = model;
});
Object.getOwnPropertyNames(db).forEach(modelName => {
const currentModel = db[modelName];
Object.getOwnPropertyNames(currentModel.rawAttributes).forEach(attributeName => {
if (
Object.prototype.hasOwnProperty.call(
currentModel.rawAttributes[attributeName],
'references'
) &&
Object.prototype.hasOwnProperty.call(
currentModel.rawAttributes[attributeName].references,
'model'
) &&
Object.prototype.hasOwnProperty.call(
currentModel.rawAttributes[attributeName].references,
'key'
)
) {
if (
!(
currentModel.rawAttributes[attributeName].references.model &&
currentModel.rawAttributes[attributeName].references.key
)
) {
console.log(
`*SKIPPED* ${modelName} ${attributeName} references a model ${currentModel.rawAttributes[attributeName].references.model} with key ${currentModel.rawAttributes[attributeName].references.key}`
);
return;
}
console.log(
`${modelName} ${attributeName} references a model ${currentModel.rawAttributes[attributeName].references.model} with key ${currentModel.rawAttributes[attributeName].references.key}`
);
const referencedTable =
tableModel[currentModel.rawAttributes[attributeName].references.model];
currentModel.belongsTo(referencedTable, { foreignKey: attributeName });
referencedTable.hasMany(currentModel, { foreignKey: attributeName });
}
});
});
// #ts-ignore
db.sequelize = sequelize;
// #ts-ignore
db.Sequelize = Sequelize;
// eslint-disable-next-line eol-last
module.exports = db;
2) inside of your resolver just reference the above:
const db = require('../assets/models/index');
To add to #CodingLittles answer which he based from here.
I added the following for making many to many assosiations:
enum Junctions {
user = 'user',
roles = 'roles',
}
enum JuntiontThrough {
userroles = 'userroles',
}
interface JunctionObject {
junctionBelongsTo?: any;
}
const checkIfAttrExists= (obj, value) => {
return Object.prototype.hasOwnProperty.call(obj, value);
};
const checkRefrence = (obj, attr, value) => {
return obj.rawAttributes[attr].references[value];
};
export const getJunction = (junc: Junctions): JunctionObject => {
const junctions = {
user: {
junctionBelongsTo: [
{ key: Junctions.roles, value: juntiontThrough.userroles }
],
},
roles: {
junctionBelongsTo: [{ key: Junctions.user, value: juntiontThrough.userroles }],
},
}[junc];
if (!junctions) return {};
return junctions;
};
const models = Object.getOwnPropertyNames(db);
models.forEach(modelName => {
const currentModel = db[modelName];
const junction = getJunction(modelName as Junctions);
if (!_.isEmpty(junction)) {
// eslint-disable-next-line array-callback-return
junction.junctionBelongsTo.reduce((key, value) => {
currentModel.belongsToMany(db[value.key], {
through: db[value.value],
});
}, {});
}
const attributes = Object.getOwnPropertyNames(currentModel.rawAttributes);
attributes.forEach(attributeName => {
if (
checkIfAttrExists(currentModel.rawAttributes[attributeName], 'references') &&
checkIfAttrExists(currentModel.rawAttributes[attributeName].references, 'model') &&
checkIfAttrExists(currentModel.rawAttributes[attributeName].references, 'key')
) {
if (
!(
checkRefrence(currentModel, attributeName, 'model') &&
checkRefrence(currentModel, attributeName, 'key')
)
) {
return;
}
const referencedTable =
tableModel[currentModel.rawAttributes[attributeName].references.model];
if (!(modelName.toString() in juntiontThrough)) {
console.log(
`${modelName} ${attributeName} references a model ${currentModel.rawAttributes[attributeName].references.model} with key ${currentModel.rawAttributes[attributeName].references.key}`
);
currentModel.belongsTo(referencedTable, { foreignKey: attributeName });
referencedTable.hasMany(currentModel, { foreignKey: attributeName });
}
}
});
})
Note that for the many to many relations to work you have to add the relations manually like I did in the getJunction function
I followed the pattern demonstrated in the typescript example on sequelize-auto (init-models.ts) - within the existing initModels function, works fine in js.
export function initModels(sequelize: Sequelize) {
Product.initModel(sequelize);
Supplier.initModel(sequelize);
Supplier.hasMany(Product, { as: "products", foreignKey: "supplierId"});
return {...

SequelizeEagerLoadingError: (parent) is not associated to (child)!

I am building an application using sequelize. I currently have 3 tables; a User, a Tour, and a Location. The Location has a n:1 relationship with the Tour. The Tour has a n:1 relationship with the user.
Without the User association, the other two tables work fine. Once I add in the user association (and I have tried to do so through a migration AND by dropping and then recreating my entire database), I get a SequelizeEagerLoadingError: Location is not associated with Tour!
Here are my models:
module.exports = function(sequelize, DataTypes) {
var Location = sequelize.define("Location", {
title: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.TEXT,
allowNull: false,
validate: {
len: [500]
}
},
address: {
type: DataTypes.TEXT,
allowNull: false
}
});
Location.associate = function(models) {
Location.belongsTo(models.Tour, {
onDelete: "cascade"
});
};
return Location;
};
module.exports = function(sequelize, DataTypes) {
var Tour = sequelize.define("Tour", {
title: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.TEXT,
allowNull: false,
validate: {
len: [1, 1000]
}
},
neighborhood: {
type: DataTypes.STRING,
allowNull: false
},
URL: {
type: DataTypes.TEXT,
allowNull: false,
validate: {
len: [1, 1000]
}
},
numberOfStops: DataTypes.INTEGER,
duration: {
type: DataTypes.INTEGER,
allowNull: false
},
tags: DataTypes.STRING
});
Tour.associate = function(models) {
Tour.hasMany(models.Location);
};
Tour.associate = function(models) {
Tour.belongsTo(models.User);
};
return Tour;
};
var bcrypt = require("bcrypt-nodejs");
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true
}
},
password: {
type: DataTypes.STRING,
allowNull: false
}
});
User.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
User.hook("beforeCreate", function(user) {
user.password = bcrypt.hashSync(
user.password,
bcrypt.genSaltSync(10),
null
);
});
User.associate = function(models) {
User.hasMany(models.Tour);
};
return User;
};
And here is the include statement where it is failing, and where we establish the link with the tourId to the location:
app.get("/tour/:id", function(req, res) {
db.Tour.findOne({
where: { id: req.params.id },
include: [db.Location]
}).then(function(tour) {
res.render("tour", {
tour: tour
});
});
});
var API = {
saveTour: function(tour) {
return $.ajax({
headers: {
"Content-Type": "application/json"
},
type: "POST",
url: "api/tours",
data: JSON.stringify(tour)
});
},
saveLocations: function(locations) {
return $.ajax({
headers: {
"Content-Type": "application/json"
},
type: "POST",
url: "api/locations",
data: JSON.stringify(locations)
});
},
getUserId: function() {
return $.ajax({
type: "GET",
url: "api/user_data"
});
}
};
var tour = {
Users: thisUser.getUserId(),
title: title,
description: description,
neighborhood: neighborhood,
URL: URL,
duration: duration,
tags: tags
};
// console.log(tour);
if (!errors.length) {
// Post our tour to the Tours table, then reveal the form and set our local tour object.
API.saveTour(tour).then(function(tour) {
document.getElementById("submit-tour").remove();
document.getElementById("tourstopssection").style.display = "block";
thisTour.setId(tour.id);
});
}
}
// Function takes in the newly created tour object, grabs DOM values for each.
function addTourLocations(e) {
e.preventDefault();
// Grab and process all of our tour stops.
var locationElements = document.getElementsByClassName("tourstop");
var areStopErrors = false;
var locations = [];
// Loop over every location element on the DOM.
for (var j = 0; j < locationElements.length; j++) {
var children = locationElements[j].children;
// Initialize this location with the tour id; we'll pass in data...
var thisLocation = {
TourId: thisTour.getId()
};
// ... by looping over the DOM children and grabbing their form values.
for (var k = 0; k < children.length; k++) {
if (
children[k].classList.value.includes("stoptitle") &&
children[k].value
) {
var stopTitle = children[k].value;
thisLocation.title = stopTitle;
}
if (
children[k].classList.value.includes("stopaddress") &&
children[k].value
) {
var stopAddress = children[k].value;
thisLocation.address = stopAddress;
}
if (
children[k].classList.value.includes("stopdescription") &&
children[k].value
) {
var stopDescription = children[k].value;
thisLocation.description = stopDescription;
}
}
// Push this location into our locations array.
locations.push(thisLocation);
Finally, this is how the app/db are synced:
require("dotenv").config();
var express = require("express");
var session = require("express-session");
var exphbs = require("express-handlebars");
var helpers = require("./lib/helpers");
var db = require("./models");
var passport = require("./config/passport");
var app = express();
var PORT = process.env.PORT || 3000;
// Middleware
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static("public"));
var hbs = exphbs.create({
defaultLayout: "main",
helpers: helpers // Require our custom Handlebars helpers.
});
//Sessions are used to keep track of our user's login status
app.use(
session({ secret: "keyboard cat", resave: true, saveUninitialized: true })
);
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next) {
res.locals.user = req.user; // Set a local variable for our user.
next();
});
// Handlebars
app.engine("handlebars", hbs.engine);
app.set("view engine", "handlebars");
// Routes
require("./routes/apiRoutes")(app);
require("./routes/htmlRoutes")(app);
var syncOptions = { force: false };
// If running a test, set syncOptions.force to true
// clearing the `testdb`
if (process.env.NODE_ENV === "test") {
syncOptions.force = true;
}
// Starting the server, syncing our models ------------------------------------/
db.sequelize.sync(syncOptions).then(function() {
app.listen(PORT, function() {
console.log(
"==> 🌎 Listening on port %s. Visit http://localhost:%s/ in your browser.",
PORT,
PORT
);
});
});
module.exports = app;
I've been googling for four days....help!
Try adding this to your associations, also why are you defining twice the association function on Tour?
module.exports = function(sequelize, DataTypes) {
var Location = sequelize.define("Location", {
//
});
Location.associate = function(models) {
Location.belongsTo(models.Tour, { as:'Tour', foreignKey:'tourId', onDelete: "cascade"});
};
return Location;
};
module.exports = function(sequelize, DataTypes) {
var Tour = sequelize.define("Tour", {
//
});
Tour.associate = function(models) {
Tour.hasMany(models.Location, { as: 'Locations', foreignKey: 'tourId'});
Tour.belongsTo(models.User, { as: 'User', foreignKey: 'userId' });
};
return Tour;
};
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
//
});
User.associate = function(models) {
User.hasMany(models.Tour, {as: 'Tours', foreignKey: 'userId'});
};
return User;
};
And add the same on the query.
db.Tour.findOne({
where: { id: req.params.id },
include: [{
model: db.Location,
as: 'Locations'
}]
}).then(function(tour) {
res.render("tour", {
tour: tour
});
});
I figured it out - the fact that I had defined the association on the tours model twice was breaking everything. Once I combined them as mentioned above, everything worked perfectly!
One other thing to note - sequelize automatically assigns the foreign key and the alias, so I left that part out.