Reputation: 1959
I am designing a system that has People and Users (all Users are people, but not all People are Users). Each of those entities can have multiple Emails. The Sequelize models are set up like this:
module.exports = function(sequelize, Sequelize) {
var Person = sequelize.define('person', {
id: {
type: Sequelize.UUID,
primaryKey: true
},
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING,
allowNull: false
},
middleName: {
type: Sequelize.STRING
},
dob: {
type: Sequelize.DATE
}
});
return Person;
};
module.exports = function (sequelize, Sequelize) {
var Company = sequelize.define('company', {
id: {
type: Sequelize.UUID,
primaryKey: true
},
name: {
type: Sequelize.STRING,
allowNull: false
},
description: {
type: Sequelize.TEXT
},
status: {
type: Sequelize.ENUM('ACTIVE', 'INACTIVE'),
defaultValue: 'ACTIVE'
}
});
return Company;
};
module.exports = function (sequelize, Sequelize) {
var User = sequelize.define('user', {
id: {
type: Sequelize.UUID,
primaryKey: true
},
username: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
},
salt: {
type: Sequelize.STRING(128),
allowNull: true
}
});
return User;
};
module.exports = function(sequelize, Sequelize) {
var Email = sequelize.define('email', {
id: {
type: Sequelize.UUID,
primaryKey: true
},
address: {
type: Sequelize.STRING,
allowNull: false
},
status: {
type: Sequelize.ENUM('ACTIVE','INACTIVE'),
allowNull: false,
defaultValue: 'ACTIVE'
}
});
return Email;
};
module.exports = function(models) {
models.Company.belongsToMany(models.User, {through: 'companiesUsers'});
models.Email.belongsToMany(models.Person, {through: 'peopleEmails'});
models.Email.belongsToMany(models.User, {through: 'usersEmails'});
models.Person.belongsToMany(models.Email, {through: 'peopleEmails'});
models.User.belongsToMany(models.Company, {through: 'companiesUsers'});
models.User.belongsToMany(models.Email, {through: 'usersEmails'});
};
module.exports = function (models, uuid, q, sequelize) {
var crypto = require('crypto');
function register(attrs) {
var salt = crypto.randomBytes(128).toString('base64').substr(0, 128),
hash = crypto.createHash('sha1'),
hashedPassword,
user,
company,
person,
deferred = q.defer(),
result = {};
hash.update(attrs.password + salt, 'utf8');
hashedPassword = hash.digest('base64');
sequelize.transaction(function(t) {
return models.User.create({
id: uuid.v4(),
username: attrs.username,
password: hashedPassword,
salt: salt
}).then(function(createdUser) {
user = createdUser;
result.user = user.dataValues;
return models.Company.create({
id: uuid.v4(),
name: attrs.companyName,
description: attrs.companyDescription || null,
status: 'ACTIVE'
});
}).then(function(createdCompany) {
company = createdCompany;
result.company = createdCompany.dataValues;
company.addUser(user);
return models.Person.create({
id: uuid.v4(),
firstName: attrs.firstName,
lastName: attrs.lastName,
middleName: attrs.middleName || null,
userId: user.id
});
}).then(function(createdPerson) {
person = createdPerson;
result.person = createdPerson.dataValues;
return models.Email.create({
id: uuid.v4(),
address: attrs.emailAddress,
status: 'ACTIVE'
});
}).then(function(email) {
email.addPerson(person);
});
}).then(function() {
deferred.resolve(result);
}).catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
}
return {
register: register
}
};
The service executes with no errors, and the companiesUsers
join entity is created just fine, but email.addPerson()
nor person.addEmail()
will create the peopleEmails
join entity.
I'm not really sure what I can do differently, but I really like Sequelize and would hate to have redo my ORM with another library because I've put a LOT of time into it!
Thanks!
Upvotes: 0
Views: 432
Reputation: 11753
Not sure if this helps, but perhaps you need a return before email.addPerson(person)? Otherwise the promise may "finish" before this step completes, and you'd miss the email-person association.
then(function(email) {
return email.addPerson(person);
^^^^^^ this was missing
});
Upvotes: 1