From 8b40efe01e7b95ea11d877fd97d825c1abb02d23 Mon Sep 17 00:00:00 2001 From: Romain Lanz Date: Wed, 4 Sep 2024 19:32:21 +0200 Subject: [PATCH] feat(orm): add loadOnce --- src/orm/base_model/index.ts | 16 ++++++++ src/types/model.ts | 6 +++ test/orm/model_belongs_to.spec.ts | 61 +++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/src/orm/base_model/index.ts b/src/orm/base_model/index.ts index 44104824..b02f762c 100644 --- a/src/orm/base_model/index.ts +++ b/src/orm/base_model/index.ts @@ -1802,6 +1802,22 @@ class BaseModelImpl implements LucidRow { .processAllForOne(this, queryClient) } + /** + * Load relationships onto the instance, but only if they are not + * already preloaded + */ + async loadOnce(relationName: any) { + this.ensureIsntDeleted() + + if (!this.$isPersisted) { + throw new Exception('Cannot lazy load relationship for an unpersisted model instance') + } + + if (!this.$preloaded[relationName]) { + return this.load(relationName) + } + } + /** * @deprecated */ diff --git a/src/types/model.ts b/src/types/model.ts index 7a2d7e5c..aa899a27 100644 --- a/src/types/model.ts +++ b/src/types/model.ts @@ -643,6 +643,12 @@ export interface LucidRow { */ load: LucidRowPreload + /** + * Load relationships onto the instance, but only if they are not + * already preloaded + */ + loadOnce: LucidRowPreload + /** * Alias for "load" * @deprecated diff --git a/test/orm/model_belongs_to.spec.ts b/test/orm/model_belongs_to.spec.ts index 8da6ccd0..41b30a20 100644 --- a/test/orm/model_belongs_to.spec.ts +++ b/test/orm/model_belongs_to.spec.ts @@ -1215,6 +1215,67 @@ test.group('Model | BelongsTo | preload', (group) => { assert.equal(profile.user.id, profile.userId) }) + test('preload once using model instance', async ({ assert, fs }) => { + const app = new AppFactory().create(fs.baseUrl, () => {}) + await app.init() + const db = getDb() + const adapter = ormAdapter(db) + const BaseModel = getBaseModel(adapter) + + let queryCount = 0 + + class User extends BaseModel { + @column({ isPrimary: true }) + declare id: number + } + + class Profile extends BaseModel { + @column({ isPrimary: true }) + declare id: number + + @column() + declare userId: number + + @column() + declare displayName: string + + @belongsTo(() => User, { + onQuery() { + queryCount++ + }, + }) + declare user: BelongsTo + } + + await db + .insertQuery() + .table('users') + .insert([{ username: 'virk' }]) + + const users = await db.query().from('users') + await db + .insertQuery() + .table('profiles') + .insert([ + { + user_id: users[0].id, + display_name: 'virk', + }, + { + user_id: users[0].id, + display_name: 'virk', + }, + ]) + + const profile = await Profile.findOrFail(1) + await profile.loadOnce('user') + await profile.loadOnce('user') + + assert.instanceOf(profile.user, User) + assert.equal(profile.user.id, profile.userId) + assert.equal(queryCount, 1) + }) + test('preload nested relations', async ({ assert, fs }) => { const app = new AppFactory().create(fs.baseUrl, () => {}) await app.init()