Implement scopes on models and support interacting with them via ModelBuilder
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -4,7 +4,7 @@ import {Connection} from '../connection/Connection'
|
||||
import {ModelBuilder} from './ModelBuilder'
|
||||
import {Container, Instantiable} from '../../di'
|
||||
import {QueryRow} from '../types'
|
||||
import {Collection} from '../../util'
|
||||
import {collect, Collection} from '../../util'
|
||||
|
||||
/**
|
||||
* Implementation of the result iterable that returns query results as instances of the defined model.
|
||||
@@ -28,13 +28,17 @@ export class ModelResultIterable<T extends Model<T>> extends AbstractResultItera
|
||||
const row = (await this.connection.query(query)).rows.first()
|
||||
|
||||
if ( row ) {
|
||||
return this.inflateRow(row)
|
||||
const inflated = await this.inflateRow(row)
|
||||
await this.processEagerLoads(collect([inflated]))
|
||||
return inflated
|
||||
}
|
||||
}
|
||||
|
||||
async range(start: number, end: number): Promise<Collection<T>> {
|
||||
const query = this.connection.dialect().renderRangedSelect(this.selectSQL, start, end)
|
||||
return (await this.connection.query(query)).rows.promiseMap<T>(row => this.inflateRow(row))
|
||||
const inflated = await (await this.connection.query(query)).rows.promiseMap<T>(row => this.inflateRow(row))
|
||||
await this.processEagerLoads(inflated)
|
||||
return inflated
|
||||
}
|
||||
|
||||
async count(): Promise<number> {
|
||||
@@ -45,7 +49,9 @@ export class ModelResultIterable<T extends Model<T>> extends AbstractResultItera
|
||||
|
||||
async all(): Promise<Collection<T>> {
|
||||
const result = await this.connection.query(this.selectSQL)
|
||||
return result.rows.promiseMap<T>(row => this.inflateRow(row))
|
||||
const inflated = await result.rows.promiseMap<T>(row => this.inflateRow(row))
|
||||
await this.processEagerLoads(inflated)
|
||||
return inflated
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +64,30 @@ export class ModelResultIterable<T extends Model<T>> extends AbstractResultItera
|
||||
.assumeFromSource(row)
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager-load eager-loaded relations for the models in the query result.
|
||||
* @param results
|
||||
* @protected
|
||||
*/
|
||||
protected async processEagerLoads(results: Collection<T>): Promise<void> {
|
||||
const eagers = this.builder.getEagerLoadedRelations()
|
||||
const model = this.make<T>(this.ModelClass)
|
||||
|
||||
for ( const name of eagers ) {
|
||||
// TODO support nested eager loads?
|
||||
|
||||
const relation = model.getRelation(name)
|
||||
const select = relation.buildEagerQuery(this.builder, results)
|
||||
|
||||
const allRelated = await select.get().collect()
|
||||
allRelated.each(result => {
|
||||
const resultRelation = result.getRelation(name as any)
|
||||
const resultRelated = resultRelation.matchResults(allRelated as any)
|
||||
resultRelation.setValue(resultRelated as any)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
clone(): ModelResultIterable<T> {
|
||||
return new ModelResultIterable(this.builder, this.connection, this.ModelClass)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user