Skip to content

Commit

Permalink
fix: Clone the preloader when cloning the query builder (#1050)
Browse files Browse the repository at this point in the history
  • Loading branch information
RomainLanz authored Sep 2, 2024
1 parent 76dd1e5 commit 18103ea
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
13 changes: 13 additions & 0 deletions src/orm/preloader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ export class Preloader implements PreloaderContract<LucidRow> {
return this
}

/**
* Clone preloader instance
*/
clone() {
const clone = new Preloader(this.model)

clone.preloads = Object.assign({}, this.preloads)
clone.sideloaded = Object.assign({}, this.sideloaded)
clone.debugQueries = this.debugQueries

return clone
}

/**
* Process of all the preloaded relationships for a single parent
*/
Expand Down
1 change: 1 addition & 0 deletions src/orm/query_builder/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ export class ModelQueryBuilder
const clonedQuery = new ModelQueryBuilder(this.knexQuery.clone(), this.model, this.client)
this.applyQueryFlags(clonedQuery)

clonedQuery.usePreloader(this.preloader.clone())
clonedQuery.sideloaded = Object.assign({}, this.sideloaded)
clonedQuery.debug(this.debugQueries)
clonedQuery.reporterData(this.customReporterData)
Expand Down
1 change: 1 addition & 0 deletions src/types/relations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1070,4 +1070,5 @@ export interface PreloaderContract<Model extends LucidRow> {

debug(debug: boolean): this
sideload(values: ModelObject): this
clone(): PreloaderContract<Model>
}
89 changes: 88 additions & 1 deletion test/orm/model_query_builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
resetTables,
getBaseModel,
} from '../../test-helpers/index.js'
import { HasMany } from '../../src/types/relations.js'
import type { HasMany } from '../../src/types/relations.js'

test.group('Model query builder', (group) => {
group.setup(async () => {
Expand Down Expand Up @@ -346,6 +346,93 @@ test.group('Model query builder', (group) => {
assert.deepEqual(user.$sideloaded, { username: 'virk' })
})

test('clone query builder with preload', async ({ fs, assert }) => {
const app = new AppFactory().create(fs.baseUrl, () => {})
await app.init()
const db = getDb()
const adapter = ormAdapter(db)
const BaseModel = getBaseModel(adapter)

class Post extends BaseModel {
@column()
declare id: number

@column()
declare userId: number

@column()
declare title: string
}
Post.boot()

class User extends BaseModel {
@column({ isPrimary: true })
declare id: number

@column()
declare username: string

@hasMany(() => Post)
declare posts: HasMany<typeof Post>
}
User.boot()

const user = await User.create({ username: 'virk' })
const posts = await user
.related('posts')
.createMany([{ title: 'Adonis 101' }, { title: 'Lucid 101' }])

const query = User.query().preload('posts')
const clone = await query.clone().firstOrFail()
assert.isArray(clone.posts)
assert.equal(clone.posts.length, posts.length)
})

test('clone query builder with preload', async ({ fs, assert }) => {
const app = new AppFactory().create(fs.baseUrl, () => {})
await app.init()
const db = getDb()
const adapter = ormAdapter(db)
const BaseModel = getBaseModel(adapter)

class Post extends BaseModel {
@column()
declare id: number

@column()
declare userId: number

@column()
declare title: string
}
Post.boot()

class User extends BaseModel {
@column({ isPrimary: true })
declare id: number

@column()
declare username: string

@hasMany(() => Post)
declare posts: HasMany<typeof Post>
}
User.boot()

const user = await User.create({ username: 'virk' })
await user.related('posts').createMany([{ title: 'Adonis 101' }, { title: 'Lucid 101' }])

const query = User.query()
const queryCloned = query.clone()

query.preload('posts')
const clone = await queryCloned.firstOrFail()
const users = await query.firstOrFail()

assert.isUndefined(clone.posts)
assert.lengthOf(users.posts, 2)
})

test('apply scopes', async ({ fs, assert }) => {
const app = new AppFactory().create(fs.baseUrl, () => {})
await app.init()
Expand Down

0 comments on commit 18103ea

Please sign in to comment.