Skip to content

Commit 2f8ac1f

Browse files
fix bug for when multiple columns reference same table
1 parent 671d479 commit 2f8ac1f

File tree

6 files changed

+104
-8
lines changed

6 files changed

+104
-8
lines changed

src/core.spec.ts

+15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { entities as fiveEntities } from '../test-utils/five/entities';
88
import { entities as sixEntities } from '../test-utils/six/entities';
99
import { entities as twelveEntities } from '../test-utils/twelve/entities';
1010
import { entities as thirteenEntities } from '../test-utils/thirteen/entities';
11+
import { entities as fourteenEntities } from '../test-utils/fourteen/entities';
1112
import { Articles } from '../test-utils/blog/models/article';
1213
const two = require('../test-utils/two/results');
1314
const three = require('../test-utils/three/results');
@@ -22,6 +23,7 @@ const ten = require('../test-utils/ten/results.json');
2223
const eleven = require('../test-utils/eleven/results.json');
2324
const twelve = require('../test-utils/twelve/results.json');
2425
const thirteen = require('../test-utils/thirteen/results.json');
26+
const fourteen = require('../test-utils/fourteen/results.json');
2527

2628
describe('createFromDatabase', () => {
2729
test('multiple rows reduce to one nested object (with all one-to-one or one-to-many tables)', () => {
@@ -1066,6 +1068,19 @@ describe('createFromDatabase', () => {
10661068
.audience.id
10671069
).toEqual(1);
10681070
});
1071+
1072+
// Issue occcurs in nestClump
1073+
// Problem when a table has two columns which reference the same other table
1074+
test('14', () => {
1075+
const core = createCore({ entities: fourteenEntities });
1076+
const persons = core.createFromDatabase(fourteen);
1077+
expect(persons?.models.length).toEqual(1);
1078+
expect(persons.models[0].id).toEqual(67);
1079+
// Known issue: A reference always uses the model's name,
1080+
// instead of some version of the column's name
1081+
expect(persons.models[0].customers?.models.length).toEqual(1);
1082+
expect(persons.models[0].customers.models[0].id).toEqual(4);
1083+
});
10691084
});
10701085

10711086
describe('createOneFromDatabase', () => {

src/core.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,23 @@ export const createCore = ({
292292
...nodes.slice(0, indexOfOldestParent + 1).reverse()
293293
];
294294
const nodeItPointsTo = parentHeirarchy.find((parent) => {
295-
const index = Object.values(
296-
getEntityByModel(model).references
297-
).indexOf(parent.constructor);
298-
if (index === -1) {
295+
const indexes = Object.values(getEntityByModel(model).references)
296+
.map((x: IModelClass, i: number) =>
297+
x === parent.constructor ? i : null
298+
)
299+
.filter((x: number | null, i) => x != null) as Array<number>;
300+
if (!indexes.length) {
299301
return false;
300302
}
301-
const property = Object.keys(getEntityByModel(model).references)[
302-
index
303-
];
304-
return model[property as keyof typeof model] === parent.id;
303+
for (const index of indexes) {
304+
const property = Object.keys(getEntityByModel(model).references)[
305+
index
306+
];
307+
if (model[property] === parent.id) {
308+
return true;
309+
}
310+
}
311+
return false;
305312
});
306313
if (isNodeAlreadySeen) {
307314
if (nodeItPointsTo && !nodePointingToIt) {

test-utils/fourteen/entities.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { personEntity } from './models/person';
2+
import { customerEntity } from './models/customer';
3+
export const entities = [personEntity, customerEntity];
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { IModel, ICollection, IColumns } from '../../../src/index';
2+
import { Person } from './person';
3+
4+
export const tableName: string = 'customer';
5+
6+
export const columns: IColumns = [
7+
'id',
8+
{ column: 'locked_to_affiliate_id', references: Person },
9+
{ column: 'locked_to_salesperson_id', references: Person }
10+
];
11+
12+
export class Customer implements IModel {
13+
id: number;
14+
lockedToAffiliateId: number;
15+
lockedToSalespersonId: number;
16+
17+
constructor(props: any) {
18+
this.id = props.id;
19+
this.lockedToAffiliateId = props.lockedToAffiliateId;
20+
this.lockedToSalespersonId = props.lockedToSalespersonId;
21+
}
22+
}
23+
24+
export class Customers implements ICollection<Customer> {
25+
models: Array<Customer>;
26+
constructor({ models }: any) {
27+
this.models = models;
28+
}
29+
}
30+
31+
export const customerEntity = {
32+
tableName,
33+
columns,
34+
Model: Customer,
35+
Collection: Customers
36+
};

test-utils/fourteen/models/person.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { IModel, ICollection, IColumns } from '../../../src/index';
2+
3+
export const tableName: string = 'person';
4+
5+
export const columns: IColumns = ['id'];
6+
7+
export class Person implements IModel {
8+
id: number;
9+
10+
constructor(props: any) {
11+
this.id = props.id;
12+
}
13+
}
14+
15+
export class Persons implements ICollection<Person> {
16+
models: Array<Person>;
17+
constructor({ models }: any) {
18+
this.models = models;
19+
}
20+
}
21+
22+
export const personEntity = {
23+
tableName,
24+
columns,
25+
Model: Person,
26+
Collection: Persons
27+
};

test-utils/fourteen/results.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"person#id": 67,
4+
"customer#id": 4,
5+
"customer#locked_to_affiliate_id": null,
6+
"customer#locked_to_salesperson_id": 67
7+
}
8+
]

0 commit comments

Comments
 (0)