Custom data type not getting assigned values for record creation

Viewed 163

I wrote a custom data type by extending Abstract, like in the example listed for the following link: https://sequelize.org/v5/manual/data-types.html. Everything appears to work until I try to save foreign keys, in this case it continues to generate a new UUID instead of getting the foreign key passed in the object to the create method.

How should I accommodate foreign keys in this case? Which method call should I overload to handle a getter situation where I need to pass in values?

The code below outlines the extended class I am using

class BinToUUID extends ABSTRACT {
        toString(options) {
            return this.toSql(options);
        }

        toSql() {
            return 'BINARY(16)';
        }

        validate(value) {
            console.log(value);
        }

        _stringify(value, options) {
            return `UUID_TO_BIN(${options.escape(value)})`;
        }

        _bindParam(value, options) {
            return `UUID_TO_BIN('${options.escape(value)}')`;
        }

        parse(value) {
            return uuidv1.parse(value);
        }
        
        _sanitize(value) {
            if (value instanceof Buffer) {
                const str = value.toString('hex');

                return [
                    str.slice(0, 8),
                    str.slice(8, 12),
                    str.slice(12, 16),
                    str.slice(16, 20),
                    str.slice(20, 32),
                ].join('-');
            } else {
                const uuid = uuidv1();
                return uuid;
            }

            return value;
        }
    }

Here is a sample of the model I am using it in:

sequelize.define("room", {
    roomId: {
        primaryKey: true,
        allowNull: false,
        type: Sequelize.BinToUUID,
        defaultValue: Sequelize.BinToUUID,
        validate: {
            notNull: true
        }
    },
    name: {
        type: DataTypes.STRING(10)
    },
    userId: {
        type: Sequelize.BinToUUID,
        references: {
            model: 'user',
            key: 'userId',
        }
    },
    groupId: {
        type: Sequelize.BinToUUID,
        references: {
            model: 'group',
            key: 'groupId',
        }
    },
    createdAt: {
        type: DataTypes.DATE
    },
    updatedAt: {
        type: DataTypes.DATE
    }
}, {
    freezeTableName: true
});

Here are the associations for the tables:

db.Room.User = db.Room.hasOne(db.User, {
    foreignKey: ‘roomId'
});
db.Room.Group = db.Room.hasOne(db.Group, {
    foreignKey: ‘groupId'
});

This is the create method begin called to save the room:

Room.create(room, {
        include: [{
            association: Room.User
        }, {
            association: Room.Group
        }]
});

I am just trying to save the foreign keys to this table. When I look into the database tables for User and Group, the values do not match the uuid primary key values. It seems like the BinToUUID datatype is overwriting the UUID that is getting passed to create method.

1 Answers

For one-to-one (primary/foreign key relationship), check out belongsTo / HasOne associations

belongsTo
https://sequelize.org/v5/class/lib/model.js~Model.html#static-method-belongsTo which has the following example:

Profile.belongsTo(User) // This will add userId to the profile table

HasOne
https://sequelize.org/v5/class/lib/associations/has-one.js~HasOne.html:

This is almost the same as belongsTo with one exception - The foreign key will be defined on the target model.

See this tutorial for examples: https://sequelize.org/v4/manual/tutorial/associations.html

This (unofficial?) article shows how foreign key is being handled: https://medium.com/@edtimmer/sequelize-associations-basics-bde90c0deeaa

Related