Skip to content

Commit

Permalink
Let models reference themselves (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
leo authored Dec 12, 2024
1 parent 70f34d0 commit 9deba39
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
8 changes: 7 additions & 1 deletion src/utils/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,13 @@ const getFieldStatement = (
if (field.kind === 'many') return null;

const actions = field.actions || {};
const targetTable = getModelBySlug(models, field.target).table;

// Passing the current model here is imporant, because it allows for creating a model
// that references itself.
const modelList = models.some((item) => item.slug === model.slug)
? models
: [...models, model];
const targetTable = getModelBySlug(modelList, field.target).table;

statement += ` REFERENCES ${targetTable}("id")`;

Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const NON_RAW_ENGINE = new Engine({
* @param raw - By default, the results are returned in a raw format, meaning in the same
* format in which SQLite returns them (rows being arrays of values). If `raw` is set to
* `false`, the rows are returned as objects, which simulates the behavior of drivers that
* are incompatible of returning raw results.
* are incapable of returning raw results.
*
* @returns A list of rows resulting from the executed statements.
*/
Expand Down
28 changes: 28 additions & 0 deletions tests/meta.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,34 @@ test('create new model that has system models associated with it', () => {
});
});

test('create new model that references itself', () => {
const fields = [
{
slug: 'parentTeam',
type: 'link',
target: 'team',
},
];

const queries: Array<Query> = [
{
create: {
model: { slug: 'team', fields },
},
},
];

const models: Array<Model> = [];

const transaction = new Transaction(queries, { models });

expect(transaction.statements[0]).toEqual({
statement:
'CREATE TABLE "teams" ("id" TEXT PRIMARY KEY, "ronin.locked" BOOLEAN, "ronin.createdAt" DATETIME, "ronin.createdBy" TEXT, "ronin.updatedAt" DATETIME, "ronin.updatedBy" TEXT, "parentTeam" TEXT REFERENCES teams("id"))',
params: [],
});
});

// Ensure that, if the `slug` of a model changes during an update, an `ALTER TABLE`
// statement is generated for it.
test('alter existing model (slug)', () => {
Expand Down

0 comments on commit 9deba39

Please sign in to comment.