I am developing an application using a node.js and express REST API to manage a sqlite database backend. I am using sequelize as an orm. Until now everything was working fine but I discovered a strange error which I cannot resolve. I have a game endpoint which handles basic game settings, like which game is it and which variant of the game as well as a flag if the game is won or there is an next player needed to do actions.
So this won and nextPlayerNeeded are as you can already guess Boolean flags. My model looks like this:
models/game.js:
'use strict';
module.exports = (sequelize, DataTypes) => {
const Game = sequelize.define(
'Game',
{
game: DataTypes.STRING,
variant: DataTypes.STRING,
inGame: DataTypes.STRING,
outGame: DataTypes.STRING,
won: DataTypes.BOOLEAN,
nextPlayerNeeded: DataTypes.BOOLEAN
},
{}
);
Game.associate = function(models) {};
return Game;
};
and the corresponding migration script is,
migrations/game.js:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Games', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
game: {
allowNull: false,
type: Sequelize.STRING
},
variant: {
allowNull: false,
type: Sequelize.STRING
},
inGame: {
allowNull: true,
type: Sequelize.STRING
},
outGame: {
allowNull: true,
type: Sequelize.STRING
},
won: {
allowNull: false,
type: Sequelize.BOOLEAN
},
nextPlayerNeeded: {
allowNull: false,
type: Sequelize.BOOLEAN
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Games');
}
};
My CRUD controller controller/gameController.js looks like this:
const { Game } = require('../models');
const fs = require('fs');
module.exports = {
getAllGames(req, res) {
return Game.findAll({
attributes: [
'id',
'game',
'variant',
'inGame',
'outGame',
'won',
'nextPlayerNeeded'
]
})
.then(games => res.status(200).send(games))
.catch(err => res.status(400).send(err));
},
getSpecificGame(req, res) {
return Game.findByPk(req.params.id, {
attributes: [
'id',
'game',
'variant',
'inGame',
'outGame',
'won',
'nextPlayerNeeded'
]
}).then(game => {
if (!game) {
return res.status(404).send({
message: `Game with id ${req.params.id} not found`
});
}
return res.status(200).send(game);
});
},
createGame(req, res) {
return Game.create({
game: req.body.game,
variant: req.body.variant,
inGame: req.body.inGame,
outGame: req.body.outGame,
won: false,
nextPlayerNeeded: false
})
.then(game => res.status(201).json(game))
.catch(err => res.status(400).send(err));
},
updateGame(req, res) {
return Game.findByPk(req.params.id, {
attributes: [
'id',
'game',
'variant',
'inGame',
'outGame',
'won',
'nextPlayerNeeded'
]
})
.then(game => {
if (!game) {
return res.status(404).send({
message: `Game with id ${req.params.id} not found`
});
}
return game
.update({
game: req.body.game || game.game,
variant: req.body.variant || game.variant,
inGame: req.body.inGame || game.inGame,
outGame: req.body.outGame || game.outGame,
won: req.body.won || game.won,
nextPlayerNeeded: req.body.nextPlayerNeeded || game.nextPlayerNeeded
})
.then(() => res.status(200).send(game))
.catch(err => res.status(400).send(err));
})
.catch(err => res.status(400).send(err));
},
deleteGame(req, res) {
return Game.findByPk(req.params.id, {
attributes: [
'id',
'game',
'variant',
'inGame',
'outGame',
'won',
'nextPlayerNeeded'
]
})
.then(game => {
if (!game) {
return res.status(404).send({
message: `Game with id ${req.params.id} not found`
});
}
return game
.destroy()
.then(() => res.status(204).send())
.catch(err => res.status(400).send(err));
})
.catch(err => res.status(400).send(err));
}
};
Now comes the fun part. I am using insomnia as a test client and I can update the instantiated game object to say that it is won (true) and that it has nextPlayerNeeded (true). So whereas the won should never be updated again to false because the game is over if won the flag nextPlayerNeeded should be false again after switching to the next player. But updating either of them to true makes it impossible to update again to false. Why is that? Why can I update those to field only once?
This is for example the response from a request where I updated the flag to true:
{
"id": 2,
"game": "X01",
"variant": "301",
"inGame": "Straight",
"outGame": "Double",
"won": false,
"nextPlayerNeeded": true,
"updatedAt": "2020-01-21T10:47:23.767Z"
}
I can update all the string flags as often as I like, but not the boolean ones.
I will be grateful fpr any hint I can get. Thanks
I did refactor my project to use GraphQL Apollo Server and Client instead of REST Api. Although in both variants I do use sequelize the GraphQL one does update it several times as I need it. So consider this unanswered but closed.