Skip to content

Commit 96e4e01

Browse files
Merge pull request bonaval#40 from bonaval/fix/reloadIfRequired
Fix/reload if required
2 parents d0797e3 + 377e1ff commit 96e4e01

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ var Temporal = function(model, sequelize, temporalOptions){
7272
return;
7373
}
7474

75+
function isVirtual(attribute) {
76+
return attributes[attribute].type instanceof Sequelize.VIRTUAL;
77+
}
78+
7579
async function getDataValues() {
7680
if (!temporalOptions.full) {
7781
return obj._previousDataValues || obj.dataValues;
@@ -85,7 +89,7 @@ var Temporal = function(model, sequelize, temporalOptions){
8589
}
8690

8791
const attributesToReload = Object.keys(attributes).filter(attribute => {
88-
if (!temporalOptions.reloadIgnoredAttributes.includes(attribute) && !(attribute in obj.dataValues)) {
92+
if (!temporalOptions.reloadIgnoredAttributes.includes(attribute) && !isVirtual(attribute) && !(attribute in obj.dataValues)) {
8993
return true;
9094
}
9195
});
@@ -97,7 +101,7 @@ var Temporal = function(model, sequelize, temporalOptions){
97101
* Model.reload() will do its magic to merge the newly fetched values directly in dataValues. #gg
98102
*/
99103
if (attributesToReload.length > 0) {
100-
await obj.reload({attributes: attributesToReload, transaction: options.transaction, paranoid: false, include: []})
104+
await obj.reload({attributes: attributesToReload, transaction: options.transaction, paranoid: false, include: null})
101105
}
102106

103107
return obj.dataValues;

test/test.js

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@ var assert = chai.assert;
77
var eventually = assert.eventually;
88

99
describe('Read-only API', function(){
10-
var sequelize, User, UserHistory;
10+
var sequelize, User, UserHistory, Group, queries = [];
11+
12+
function logging(message) {
13+
if (process.env.LOGGING === 'true') {
14+
console.log(message);
15+
}
16+
17+
queries.push(message.substring(message.indexOf(':') + 2));
18+
}
1119

1220
function freshDB(){
1321
return freshDBWithOptions();
@@ -22,12 +30,21 @@ describe('Read-only API', function(){
2230
sequelize = new Sequelize('', '', '', {
2331
dialect: 'sqlite',
2432
storage: __dirname + '/.test.sqlite',
25-
logging: process.env.LOGGING === 'true' ? console.log : false
33+
logging
2634
});
2735
User = Temporal(sequelize.define('User', {
28-
name: Sequelize.TEXT
36+
name: Sequelize.TEXT,
37+
virtual: Sequelize.VIRTUAL(Sequelize.STRING, ['name']),
2938
}, modelOptions), sequelize, temporalOptions);
3039
UserHistory = sequelize.models.UserHistory;
40+
41+
Group = sequelize.define('Group', {
42+
name: Sequelize.TEXT
43+
});
44+
Group.hasMany(User);
45+
User.belongsTo(Group);
46+
User.addScope('withGroup', { include: [Group] });
47+
3148
return sequelize.sync({ force: true });
3249
}
3350

@@ -41,6 +58,10 @@ describe('Read-only API', function(){
4158
}
4259
}
4360

61+
afterEach(function() {
62+
queries.length = 0;
63+
});
64+
4465
describe('hooks', function(){
4566
beforeEach(freshDB);
4667
it('onCreate: should not store the new version in history db' , function(){
@@ -328,7 +349,7 @@ describe('Read-only API', function(){
328349

329350
it('onUpdate: should store the previous version to the historyDB even if entity was partially loaded' , async function(){
330351
const created = await User.create({ name: 'name' });
331-
const user = await User.findByPk(created.id, { attributes: ['id', 'name'] }); // Don't fetch timestamps
352+
const user = await User.scope('withGroup').findByPk(created.id, { attributes: ['id', 'name'] }); // Don't fetch timestamps
332353

333354
await user.update({ name: 'newName' });
334355
await user.update({ name: 'thirdName' });
@@ -348,6 +369,46 @@ describe('Read-only API', function(){
348369
assert.equal('name', initial.name);
349370
assert.equal('newName', firstUpdate.name);
350371
assert.equal('thirdName', secondUpdate.name);
372+
373+
const selects = queries.filter(query => query.startsWith('SELECT'));
374+
375+
assert.deepEqual(selects, [
376+
"SELECT `User`.`id`, `User`.`name`, `Group`.`id` AS `Group.id`, `Group`.`name` AS `Group.name`, `Group`.`createdAt` AS `Group.createdAt`, `Group`.`updatedAt` AS `Group.updatedAt` FROM `Users` AS `User` LEFT OUTER JOIN `Groups` AS `Group` ON `User`.`GroupId` = `Group`.`id` WHERE (`User`.`deletedAt` IS NULL AND `User`.`id` = 1);",
377+
"SELECT `createdAt`, `GroupId` FROM `Users` AS `User` WHERE `User`.`id` = 1;", // Reload for first update, no includes and only required fields. Second update does not need a reload
378+
"SELECT `id`, `name`, `createdAt`, `updatedAt`, `deletedAt`, `hid`, `archivedAt` FROM `UserHistories` AS `UserHistory`;"
379+
])
380+
});
381+
382+
it('onUpdate: should not reload virtual fields' , async function(){
383+
const created = await User.create({ name: 'name' });
384+
const user = await User.findByPk(created.id, { attributes: ['id', 'name', 'createdAt', 'GroupId'] }); // Don't fetch timestamps
385+
386+
await user.update({ name: 'newName' });
387+
await user.update({ name: 'thirdName' });
388+
389+
const history = await UserHistory.findAll();
390+
391+
assert.equal(history.length, 3, 'initial revision and to updates saved');
392+
393+
const [initial, firstUpdate, secondUpdate] = history;
394+
395+
assert.equal(+initial.createdAt, +firstUpdate.createdAt, 'createdAt was saved during first update, despite not being eagerly loaded');
396+
assert.equal(+initial.createdAt, +secondUpdate.createdAt, 'createdAt was saved during second update, despite not being eagerly loaded');
397+
398+
assert.isAtLeast(firstUpdate.updatedAt, initial.createdAt, 'updatedAt was saved during first update');
399+
assert.isAtLeast(secondUpdate.updatedAt, firstUpdate.updatedAt, 'updatedAt was saved during second update');
400+
401+
assert.equal('name', initial.name);
402+
assert.equal('newName', firstUpdate.name);
403+
assert.equal('thirdName', secondUpdate.name);
404+
405+
const selects = queries.filter(query => query.startsWith('SELECT'));
406+
407+
// No reload
408+
assert.deepEqual(selects, [
409+
"SELECT `id`, `name`, `createdAt`, `GroupId` FROM `Users` AS `User` WHERE (`User`.`deletedAt` IS NULL AND `User`.`id` = 1);",
410+
"SELECT `id`, `name`, `createdAt`, `updatedAt`, `deletedAt`, `hid`, `archivedAt` FROM `UserHistories` AS `UserHistory`;"
411+
])
351412
});
352413

353414
});

0 commit comments

Comments
 (0)