Last active
August 29, 2015 14:21
-
-
Save saneki/52c30604144adf4bd408 to your computer and use it in GitHub Desktop.
sequelize_associations_in_transaction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// sequelize | |
this._sequelize = new Sequelize(null, null, null, { | |
dialect: 'sqlite', | |
storage: path, | |
define: { | |
paranoid: true, | |
underscored: true, | |
underscoredAll: true | |
} | |
}); | |
// RawrUser (unsure of a better way to deal with COLLATE NOCASE?) | |
var RawrUser = models.RawrUser = sequelize.define('RawrUser', { | |
channel: { type: Sequelize.STRING(64) + ' COLLATE NOCASE', allowNull: false }, | |
username: { type: Sequelize.STRING(64) + ' COLLATE NOCASE', allowNull: false }, | |
points: { type: Sequelize.INTEGER, defaultValue: 0, allowNull: false }, | |
subpoints: { type: Sequelize.INTEGER, defaultValue: 0, allowNull: false }, | |
remind: { type: Sequelize.BOOLEAN, defaultValue: true, allowNull: false } | |
}, { | |
instanceMethods: { | |
/** | |
* Whether or not this user has a ticket of a specific type. | |
* @param {String} type Ticket type to check for | |
*/ | |
hasTicket: function(type) { | |
return this.getRawrTickets({ where: { type: type } }).then(function(tickets) { | |
return tickets && tickets.length > 0; | |
}); | |
} | |
} | |
}); | |
// RawrTicket | |
var RawrTicket = models.RawrTicket = sequelize.define('RawrTicket', { | |
type: { type: Sequelize.ENUM('sketch'), defaultValue: 'sketch', allowNull: false } | |
}, { | |
updatedAt: false | |
}); | |
// Associations | |
RawrTicket.belongsTo(RawrUser); | |
RawrUser.hasMany(RawrTicket); | |
// ... | |
// No transaction, associations work but performing without a transaction is risky | |
if(user.points >= cost) { | |
// Update user's points | |
return user.update({ | |
points: (user.points - cost) | |
}).then(function() { | |
// Add the ticket | |
var ticket = RawrTicket.build({ | |
type: type, | |
RawrUser: user | |
}); | |
return user.addRawrTicket(ticket); | |
}); | |
} else { | |
throw new Error('Not enough points to purchase ticket'); | |
} | |
// Managed Transaction, associations don't work for some reason. | |
// A RawrTicket will be created and inserted into the database, but with a null foreign key which | |
// should point to RawrUser (although when printed to console, the ticket's dataValues show the | |
// foreign key rawr_user_id with the expected user id) | |
if(user.points >= cost) { | |
return sequelize.transaction(function(t) { | |
var TRANSACTION = { transaction: t }; | |
// Update user's points | |
return user.update({ | |
points: (user.points - cost) | |
}, TRANSACTION).then(function() { | |
// Add the ticket | |
var ticket = RawrTicket.build({ | |
type: type, | |
RawrUser: user | |
}); | |
return user.addRawrTicket(ticket, TRANSACTION).then(function(ticket) { | |
// Only added this to print out the object with dataValues | |
console.log(ticket); | |
}); | |
}); | |
}); | |
} else { | |
throw new Error('Not enough points to purchase ticket'); | |
} | |
// As is seen in the data values, rawr_user_id seems fine and valid, but it isn't seen at all in the sql query | |
{ dataValues: | |
{ id: 5, | |
type: 'sketch', | |
rawr_user_id: 1, // A valid user id | |
created_at: Sun May 17 2015 03:30:13 GMT-0500 (CDT) }, | |
_previousDataValues: | |
{ type: undefined, | |
rawr_user_id: undefined, | |
id: null, | |
points: undefined, | |
updated_at: undefined, | |
created_at: Sun May 17 2015 03:30:13 GMT-0500 (CDT) }, | |
_changed: | |
{ type: true, | |
rawr_user_id: true, | |
id: true, | |
points: false, | |
updated_at: false, | |
created_at: false }, | |
... | |
} | |
// The sql query log output, with the INSERT statement neglecting rawr_user_id | |
Executing (f5698319-44cc-4acc-a8e8-3832e1df5abe): BEGIN TRANSACTION; | |
Executing (f5698319-44cc-4acc-a8e8-3832e1df5abe): -- SQLite is not able to choose the isolation level REPEATABLE READ. | |
Executing (f5698319-44cc-4acc-a8e8-3832e1df5abe): -- SQLite does not support SET autocommit. | |
Executing (f5698319-44cc-4acc-a8e8-3832e1df5abe): UPDATE `rawr_users` SET `points`=50,`updated_at`='2015-05-17 08:30:13.000 +00:00' WHERE `id` = 1 | |
Executing (f5698319-44cc-4acc-a8e8-3832e1df5abe): SELECT `id`, `type`, `created_at`, `deleted_at`, `rawr_user_id` FROM `rawr_tickets` AS `RawrTicket` WHERE (`RawrTicket`.`deleted_at` IS NULL AND (`RawrTicket`.`rawr_user_id` = 1 AND `RawrTicket`.`id` IS NULL)); | |
Executing (f5698319-44cc-4acc-a8e8-3832e1df5abe): INSERT INTO `rawr_tickets` (`created_at`) VALUES ('2015-05-17 08:30:13.000 +00:00'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment