fix: avoid bug when update other field (#51)

* fix: avoid bug when update other field

* fix: optimize logic
This commit is contained in:
Junyi 2021-01-01 11:42:45 +08:00 committed by GitHub
parent 6a9bf9572c
commit 9fcf6fbd59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 6 deletions

View File

@ -170,5 +170,27 @@ describe('radio', () => {
expect(posts.map(({ pinned }) => pinned)).toEqual([false, false, true]);
});
it('update other fields should not effect radio field', async () => {
const Post = db.getModel('posts');
await Post.bulkCreate([
{ title: 'bug1' },
{ title: 'bug2' },
{ title: 'bug3' }
]);
const post = await Post.findByPk(2);
await post.update({
pinned: true,
});
await post.update({
status: 'draft'
});
const posts = await Post.findAll({ order: [['id', 'ASC']] });
expect(posts.map(({ pinned }) => pinned)).toEqual([ false, true, false ]);
});
});
});

View File

@ -1,4 +1,5 @@
import {
Op,
Utils,
DataType,
DataTypes,
@ -796,7 +797,7 @@ export class Radio extends BOOLEAN {
public readonly options: Options.RadioOptions;
static async beforeSaveHook(this: Radio, model, options) {
static async beforeCreateHook(this: Radio, model, options) {
const { name, defaultValue = false, scope = [] } = this.options;
const { transaction } = options;
const value = model.get(name) || defaultValue;
@ -807,8 +808,19 @@ export class Radio extends BOOLEAN {
}
}
static async beforeUpdateHook(this: Radio, model, options) {
const { name, scope = [] } = this.options;
const { transaction, association } = options;
if (model.changed(name) && model.get(name) && !association) {
const where = model.getValuesByFieldNames(scope);
const { primaryKeyAttribute } = model.constructor;
where[primaryKeyAttribute] = { [Op.ne]: model.get(primaryKeyAttribute) }
await this.setOthers({ where, transaction });
}
}
static async beforeBulkCreateHook(this: Radio, models, options) {
const { name, defaultValue = false, scope = [] } = this.options;
const { scope = [] } = this.options;
const { transaction } = options;
// 如果未配置范围限定,则可以进行性能优化处理(常用情况)。
@ -847,9 +859,8 @@ export class Radio extends BOOLEAN {
super({ ...options, type: 'boolean' }, context);
const Model = context.sourceTable.getModel();
// TODO(feature): 可考虑策略模式,以在需要时对外提供接口
const beforeSaveHook = Radio.beforeSaveHook.bind(this);
Model.addHook('beforeCreate', beforeSaveHook);
Model.addHook('beforeUpdate', beforeSaveHook);
Model.addHook('beforeCreate', Radio.beforeCreateHook.bind(this));
Model.addHook('beforeUpdate', Radio.beforeUpdateHook.bind(this));
// Model.addHook('beforeUpsert', beforeSaveHook);
Model.addHook('beforeBulkCreate', Radio.beforeBulkCreateHook.bind(this));
// TODO(optimize): bulkUpdate 的 hooks 参数不一样,没有对象列表,考虑到很少用,暂时不实现
@ -865,7 +876,14 @@ export class Radio extends BOOLEAN {
const table = this.context.sourceTable;
const Model = table.getModel();
// 防止 beforeBulkUpdate hook 死循环,因外层 bulkUpdate 并不禁用,正常更新无影响。
await Model.update({ [name]: false }, { where, transaction, hooks: false });
await Model.update({ [name]: false }, {
where: {
...where,
[name]: true
},
transaction,
hooks: false
});
}
async makeGroup(this: Radio, models, { where = {}, transaction }) {