daniel0mullins
daniel0mullins

Reputation: 1959

Sequelize Associations not being created

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:

Models

Person

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;
};

Company

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;
};

User

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;
};

Email

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;
};

Relations

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'});
};

Service

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
}
};

Result

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

Answers (1)

st.never
st.never

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

Related Questions