Skip to content

Commit 7cc36c3

Browse files
committed
fix(relation): make sure query.first eagerloads
query().first() was not entertaining eagerloads, so fixed that
1 parent b87eb40 commit 7cc36c3

File tree

3 files changed

+83
-35
lines changed

3 files changed

+83
-35
lines changed

src/Lucid/Model/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,12 @@ class Model {
872872
_.each(result, (values, name) => this.setRelated(name, values))
873873
}
874874

875+
async loadMany (eagerLoadMap) {
876+
const eagerLoad = new EagerLoad(eagerLoadMap)
877+
const result = await eagerLoad.loadOne(this)
878+
_.each(result, (values, name) => this.setRelated(name, values))
879+
}
880+
875881
/**
876882
* Returns an instance of hasOne relation
877883
*

src/Lucid/QueryBuilder/index.js

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,27 @@ class QueryBuilder {
135135
* @private
136136
*/
137137
_mapRowsToInstances (rows) {
138-
return rows.map((row) => {
139-
const modelInstance = new this.model()
140-
modelInstance.newUp(_.omitBy(row, (value, field) => {
141-
if (this._sideLoaded.indexOf(field) > -1) {
142-
modelInstance.$sideLoaded[field] = value
143-
return true
144-
}
145-
}))
146-
return modelInstance
147-
})
138+
return rows.map((row) => this._mapRowToInstance(row))
139+
}
140+
141+
/**
142+
* Maps a single row to model instance
143+
*
144+
* @method _mapRowToInstance
145+
*
146+
* @param {Object} row
147+
*
148+
* @return {Model}
149+
*/
150+
_mapRowToInstance (row) {
151+
const modelInstance = new this.model()
152+
modelInstance.newUp(_.omitBy(row, (value, field) => {
153+
if (this._sideLoaded.indexOf(field) > -1) {
154+
modelInstance.$sideLoaded[field] = value
155+
return true
156+
}
157+
}))
158+
return modelInstance
148159
}
149160

150161
/**
@@ -216,6 +227,38 @@ class QueryBuilder {
216227
return new this.model.serializer(modelInstances)
217228
}
218229

230+
/**
231+
* Returns the first row from the database.
232+
*
233+
* @method first
234+
*
235+
* @return {Model|Null}
236+
*/
237+
async first () {
238+
/**
239+
* Apply all the scopes before fetching
240+
* data
241+
*/
242+
this._applyScopes()
243+
244+
const row = await this.query.first()
245+
if (!row) {
246+
return null
247+
}
248+
249+
const modelInstance = this._mapRowToInstance(row)
250+
251+
/**
252+
* Eagerload relations when defined on query
253+
*/
254+
if (_.size(this._eagerLoads)) {
255+
await modelInstance.loadMany(this._eagerLoads)
256+
}
257+
258+
this.model.$hooks.after.exec('find', modelInstance)
259+
return modelInstance
260+
}
261+
219262
/**
220263
* Paginate records, same as fetch but returns a
221264
* collection with pagination info
@@ -268,31 +311,6 @@ class QueryBuilder {
268311
return this.query.update(this.model.formatDates(values))
269312
}
270313

271-
/**
272-
* Returns the first row from the database.
273-
*
274-
* @method first
275-
*
276-
* @return {Model|Null}
277-
*/
278-
async first () {
279-
/**
280-
* Apply all the scopes before fetching
281-
* data
282-
*/
283-
this._applyScopes()
284-
285-
const result = await this.query.first()
286-
if (!result) {
287-
return null
288-
}
289-
290-
const modelInstance = new this.model()
291-
modelInstance.newUp(result)
292-
this.model.$hooks.after.exec('find', modelInstance)
293-
return modelInstance
294-
}
295-
296314
/**
297315
* Returns an array of primaryKeys
298316
*

test/unit/lucid-relations.spec.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,4 +1202,28 @@ test.group('Relations | HasOne', (group) => {
12021202
assert.equal(userQuery.sql, helpers.formatQuery('select * from "users"'))
12031203
assert.equal(profileQuery.sql, helpers.formatQuery('select *, (select count(*) from "pictures" where profiles.id = pictures.profile_id) as "picture_count" from "profiles" where "user_id" in (?, ?)'))
12041204
})
1205+
1206+
test('eagerload when calling first', async (assert) => {
1207+
class Profile extends Model {
1208+
}
1209+
1210+
class User extends Model {
1211+
profile () {
1212+
return this.hasOne(Profile)
1213+
}
1214+
}
1215+
1216+
User._bootIfNotBooted()
1217+
Profile._bootIfNotBooted()
1218+
1219+
let profileQuery = null
1220+
1221+
Profile.onQuery((query) => profileQuery = query)
1222+
1223+
await ioc.use('Database').table('users').insert({ username: 'virk' })
1224+
await ioc.use('Database').table('profiles').insert({ user_id: 1, profile_name: 'virk', likes: 3 })
1225+
1226+
const user = await User.query().with('profile').first()
1227+
assert.instanceOf(user.getRelated('profile'), Profile)
1228+
})
12051229
})

0 commit comments

Comments
 (0)