diff --git a/src/orm/base_model/index.ts b/src/orm/base_model/index.ts index 44104824..93affd18 100644 --- a/src/orm/base_model/index.ts +++ b/src/orm/base_model/index.ts @@ -1802,6 +1802,16 @@ class BaseModelImpl implements LucidRow { .processAllForOne(this, queryClient) } + /** + * Load relationships onto the instance, but only if they are not + * already preloaded + */ + async loadOnce(relationName: any) { + if (!this.$preloaded[relationName]) { + return this.load(relationName) + } + } + /** * @deprecated */ diff --git a/src/types/model.ts b/src/types/model.ts index 7a2d7e5c..7e698d17 100644 --- a/src/types/model.ts +++ b/src/types/model.ts @@ -36,6 +36,7 @@ import { WhereHas, WithAggregate, WithCount, + PreloadWithoutCallback, } from './relations.js' /** @@ -314,6 +315,9 @@ export interface LucidRowPreload extends Preload) => void): Promise } +export interface LucidRowPreloadOnce + extends PreloadWithoutCallback> {} + export interface LucidRowAggregate extends Preload> { (callback: (preloader: PreloaderContract) => void): Promise } @@ -643,6 +647,12 @@ export interface LucidRow { */ load: LucidRowPreload + /** + * Load relationships onto the instance, but only if they are not + * already preloaded + */ + loadOnce: LucidRowPreloadOnce + /** * Alias for "load" * @deprecated diff --git a/src/types/relations.ts b/src/types/relations.ts index 0aae34ba..5c338795 100644 --- a/src/types/relations.ts +++ b/src/types/relations.ts @@ -1058,6 +1058,10 @@ export interface Preload { ): Builder } +export interface PreloadWithoutCallback { + >(relation: Name): Builder +} + /** * Shape of the preloader to preload relationships */ 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()