Fix/save through table data (#1714)

* fix: save through table data

* chore: variable name

* fix: format
This commit is contained in:
ChengLei Shao 2023-04-17 14:46:16 +08:00 committed by GitHub
parent 1654b42037
commit 9fc8f5389b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 100 additions and 22 deletions

View File

@ -181,6 +181,80 @@ describe('repository.find', () => {
}); });
}); });
describe('repository create with belongs to many', () => {
let db: Database;
beforeEach(async () => {
db = mockDatabase({
tablePrefix: '',
});
await db.clean({ drop: true });
});
afterEach(async () => [await db.close()]);
it('should save value at through table', async () => {
const Product = db.collection({
name: 'products',
fields: [
{ type: 'string', name: 'name' },
{ type: 'integer', name: 'price' },
],
});
const OrderProduct = db.collection({
name: 'orders_products',
fields: [{ type: 'integer', name: 'quantity' }],
});
const Order = db.collection({
name: 'orders',
fields: [
{
type: 'belongsToMany',
name: 'products',
through: 'orders_products',
},
],
});
await db.sync();
await Product.repository.create({
values: [
{
name: 'product1',
price: 100,
},
{
name: 'product2',
price: 200,
},
],
});
const p1 = await Product.repository.findOne({
filter: { name: 'product1' },
});
await Order.repository.create({
values: {
products: [
{
id: p1.get('id'),
orders_products: {
quantity: 20,
},
},
],
},
});
const through = await OrderProduct.repository.findOne();
expect(through.get('quantity')).toBe(20);
});
});
describe('repository.create', () => { describe('repository.create', () => {
let db: Database; let db: Database;
let User: Collection; let User: Collection;

View File

@ -6,10 +6,11 @@ import {
HasOne, HasOne,
Hookable, Hookable,
ModelStatic, ModelStatic,
Transactionable Transactionable,
} from 'sequelize'; } from 'sequelize';
import { Model } from './model'; import { Model } from './model';
import { UpdateGuard } from './update-guard'; import { UpdateGuard } from './update-guard';
import lodash from 'lodash';
function isUndefinedOrNull(value: any) { function isUndefinedOrNull(value: any) {
return typeof value === 'undefined' || value === null; return typeof value === 'undefined' || value === null;
@ -396,38 +397,40 @@ export async function updateMultipleAssociation(
return; return;
} }
if (!Array.isArray(value)) { value = lodash.castArray(value);
value = [value];
}
const list1 = []; // to be setted const setItems = []; // to be setted
const list2 = []; // to be added const objectItems = []; // to be added
const created = [];
// iterate item in value
for (const item of value) { for (const item of value) {
if (isUndefinedOrNull(item)) { if (isUndefinedOrNull(item)) {
continue; continue;
} }
if (isStringOrNumber(item)) { if (isStringOrNumber(item)) {
list1.push(item); setItems.push(item);
} else if (item instanceof Model) { } else if (item instanceof Model) {
list1.push(item); setItems.push(item);
} else if (item.sequelize) { } else if (item.sequelize) {
list1.push(item); setItems.push(item);
} else if (typeof item === 'object') { } else if (typeof item === 'object') {
const targetKey = (association as any).targetKey || 'id'; const targetKey = (association as any).targetKey || 'id';
if (item[targetKey]) { if (item[targetKey]) {
created.push(item[targetKey]); setItems.push(item[targetKey]);
list1.push(item[targetKey]);
} }
list2.push(item);
objectItems.push(item);
} }
} }
// associate targets in lists1 // associate targets in lists1
await model[setAccessor](list1, { transaction, context, individualHooks: true }); await model[setAccessor](setItems, { transaction, context, individualHooks: true });
const list3 = []; const newItems = [];
for (const item of list2) {
for (const item of objectItems) {
const pk = association.target.primaryKeyAttribute; const pk = association.target.primaryKeyAttribute;
const through = (<any>association).through ? (<any>association).through.model.name : null; const through = (<any>association).through ? (<any>association).through.model.name : null;
@ -446,13 +449,14 @@ export async function updateMultipleAssociation(
if (isUndefinedOrNull(item[pk])) { if (isUndefinedOrNull(item[pk])) {
// create new record // create new record
const instance = await model[createAccessor](item, accessorOptions); const instance = await model[createAccessor](item, accessorOptions);
await updateAssociations(instance, item, { await updateAssociations(instance, item, {
...options, ...options,
transaction, transaction,
associationContext: association, associationContext: association,
updateAssociationValues: keys, updateAssociationValues: keys,
}); });
list3.push(instance); newItems.push(instance);
} else { } else {
// set & update record // set & update record
const instance = await association.target.findByPk<any>(item[pk], { const instance = await association.target.findByPk<any>(item[pk], {
@ -462,9 +466,9 @@ export async function updateMultipleAssociation(
continue; continue;
} }
const addAccessor = association.accessors.add; const addAccessor = association.accessors.add;
if (!created.includes(item[pk])) {
await model[addAccessor](item[pk], accessorOptions); await model[addAccessor](item[pk], accessorOptions);
}
if (!recursive) { if (!recursive) {
continue; continue;
} }
@ -477,11 +481,11 @@ export async function updateMultipleAssociation(
associationContext: association, associationContext: association,
updateAssociationValues: keys, updateAssociationValues: keys,
}); });
list3.push(instance); newItems.push(instance);
} }
} }
model.setDataValue(key, list1.concat(list3)); model.setDataValue(key, setItems.concat(newItems));
} catch (error) { } catch (error) {
throw error; throw error;
} }