mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 12:26:22 +00:00
feat: belongs to many on delete (#1158)
This commit is contained in:
parent
4085ed0db7
commit
78fe77e2cf
@ -1,5 +1,5 @@
|
||||
import { omit } from 'lodash';
|
||||
import { BelongsToOptions as SequelizeBelongsToOptions, Utils } from 'sequelize';
|
||||
import { BelongsTo, BelongsToOptions as SequelizeBelongsToOptions, Utils } from 'sequelize';
|
||||
import { Reference } from '../features/ReferencesMap';
|
||||
import { checkIdentifier } from '../utils';
|
||||
import { BaseRelationFieldOptions, RelationField } from './relation-field';
|
||||
@ -16,18 +16,22 @@ export class BelongsToField extends RelationField {
|
||||
return target || Utils.pluralize(name);
|
||||
}
|
||||
|
||||
reference(association): Reference {
|
||||
static toReference(db, association, onDelete) {
|
||||
const targetKey = association.targetKey;
|
||||
|
||||
return {
|
||||
sourceCollectionName: this.database.modelCollection.get(association.source).name,
|
||||
sourceCollectionName: db.modelCollection.get(association.source).name,
|
||||
sourceField: association.foreignKey,
|
||||
targetField: targetKey,
|
||||
targetCollectionName: this.database.modelCollection.get(association.target).name,
|
||||
onDelete: this.options.onDelete,
|
||||
targetCollectionName: db.modelCollection.get(association.target).name,
|
||||
onDelete: onDelete,
|
||||
};
|
||||
}
|
||||
|
||||
reference(association): Reference {
|
||||
return BelongsToField.toReference(this.database, association, this.options.onDelete);
|
||||
}
|
||||
|
||||
bind() {
|
||||
const { database, collection } = this.context;
|
||||
const Target = this.TargetModel;
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { omit } from 'lodash';
|
||||
import { BelongsToManyOptions as SequelizeBelongsToManyOptions, Utils } from 'sequelize';
|
||||
import { Collection } from '../collection';
|
||||
import { Reference } from '../features/ReferencesMap';
|
||||
import { checkIdentifier } from '../utils';
|
||||
import { BelongsToField } from './belongs-to-field';
|
||||
import { MultipleRelationFieldOptions, RelationField } from './relation-field';
|
||||
|
||||
export class BelongsToManyField extends RelationField {
|
||||
@ -25,6 +27,15 @@ export class BelongsToManyField extends RelationField {
|
||||
return this.options.otherKey;
|
||||
}
|
||||
|
||||
references(association): Reference[] {
|
||||
const db = this.context.database;
|
||||
|
||||
return [
|
||||
BelongsToField.toReference(db, association.toSource, this.options.onDelete),
|
||||
BelongsToField.toReference(db, association.toTarget, this.options.onDelete),
|
||||
];
|
||||
}
|
||||
|
||||
bind() {
|
||||
const { database, collection } = this.context;
|
||||
|
||||
@ -86,6 +97,8 @@ export class BelongsToManyField extends RelationField {
|
||||
|
||||
Through.addIndex([this.options.foreignKey]);
|
||||
Through.addIndex([this.options.otherKey]);
|
||||
|
||||
this.references(association).forEach((reference) => this.database.referenceMap.addReference(reference));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -97,6 +110,11 @@ export class BelongsToManyField extends RelationField {
|
||||
database.removePendingField(this);
|
||||
// 删掉 model 的关联字段
|
||||
|
||||
const association = collection.model.associations[this.name];
|
||||
if (association) {
|
||||
this.references(association).forEach((reference) => this.database.referenceMap.removeReference(reference));
|
||||
}
|
||||
|
||||
this.clearAccessors();
|
||||
delete collection.model.associations[this.name];
|
||||
}
|
||||
|
@ -13,6 +13,58 @@ describe('reference integrity check', () => {
|
||||
await app.destroy();
|
||||
});
|
||||
|
||||
it('should delete cascade on belongs to many relation', async () => {
|
||||
const posts = db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{ type: 'string', name: 'title' },
|
||||
{ type: 'belongsToMany', name: 'tags', onDelete: 'CASCADE' },
|
||||
],
|
||||
});
|
||||
|
||||
const tags = db.collection({
|
||||
name: 'tags',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'posts',
|
||||
onDelete: 'CASCADE',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
const post = await posts.repository.create({
|
||||
values: {
|
||||
title: 'post',
|
||||
tags: [{ name: 't1' }, { name: 't2' }],
|
||||
},
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
const throughModel = posts.model.associations.tags.through.model;
|
||||
|
||||
expect(await throughModel.count()).toEqual(2);
|
||||
|
||||
await post.destroy();
|
||||
|
||||
expect(await throughModel.count()).toEqual(0);
|
||||
|
||||
expect(db.referenceMap.getReferences('posts').length > 0).toBeTruthy();
|
||||
expect(db.referenceMap.getReferences('tags').length > 0).toBeTruthy();
|
||||
|
||||
tags.removeField('posts');
|
||||
tags.removeField('tags');
|
||||
|
||||
expect(db.referenceMap.getReferences('posts').length == 0).toBeTruthy();
|
||||
expect(db.referenceMap.getReferences('tags').length == 0).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should clean reference after collection destroy', async () => {
|
||||
const users = db.collection({
|
||||
name: 'users',
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 67f51c7fdd132ab12821f31f737b6f0cfb70d212
|
||||
Subproject commit 5a5fba41ae1cecaf3b073fcb610e9dc68dad0b85
|
Loading…
Reference in New Issue
Block a user