Skip to content

Commit

Permalink
refactor: consistently reflect query options on the model instances
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Jan 12, 2020
1 parent 7e2cb19 commit 45ea50e
Show file tree
Hide file tree
Showing 3 changed files with 290 additions and 20 deletions.
2 changes: 1 addition & 1 deletion adonis-typings/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ declare module '@ioc:Adonis/Lucid/Model' {
$options?: ModelOptions
$trx?: TransactionClientContract,

$setOptionsOrTrx (options: ModelAdapterOptions): void
$setOptionsAndTrx (options?: ModelAdapterOptions): void

/**
* Gives an option to the end user to define constraints for update, insert
Expand Down
32 changes: 13 additions & 19 deletions src/Orm/BaseModel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,7 @@ export class BaseModel implements ModelContract {
instance.$consumeAdapterResult(adapterResult, sideloadAttributes)
instance.$hydrateOriginals()

if (options) {
instance.$setOptionsOrTrx(options)
}

instance.$setOptionsAndTrx(options)
instance.$persisted = true
instance.$isLocal = false

Expand Down Expand Up @@ -373,10 +370,7 @@ export class BaseModel implements ModelContract {
): Promise<InstanceType<T>> {
const instance = new this()
instance.fill(values)

if (options) {
instance.$setOptionsOrTrx(options)
}
instance.$setOptionsAndTrx(options)

await instance.save()
return instance as InstanceType<T>
Expand Down Expand Up @@ -451,7 +445,7 @@ export class BaseModel implements ModelContract {
if (!row) {
row = new this() as InstanceType<T>
row.fill(Object.assign({}, search, savePayload))
row.$setOptionsOrTrx(query.clientOptions)
row.$setOptionsAndTrx(query.clientOptions)
}

return row
Expand Down Expand Up @@ -507,7 +501,8 @@ export class BaseModel implements ModelContract {
})
})

const existingRows = await this.query(options).whereIn(castKey, uniqueKeyValues)
const query = this.query(options)
const existingRows = await query.whereIn(castKey, uniqueKeyValues)

/**
* Return existing or create missing rows in the same order as the original
Expand All @@ -522,10 +517,7 @@ export class BaseModel implements ModelContract {

const instance = new this() as InstanceType<T>
instance.fill(row)
if (options) {
instance.$setOptionsOrTrx(options)
}

instance.$setOptionsAndTrx(query.clientOptions)
return instance
})
}
Expand Down Expand Up @@ -810,15 +802,17 @@ export class BaseModel implements ModelContract {
}

/**
* Set options on the model instance by giving preference to the transaction
* client.
* Set options on the model instance along with transaction
*/
public $setOptionsOrTrx (options: ModelAdapterOptions): void {
public $setOptionsAndTrx (options?: ModelAdapterOptions): void {
if (!options) {
return
}

if (options.client && options.client.isTransaction) {
this.$trx = options.client as TransactionClientContract
} else {
this.$options = options
}
this.$options = options
}

/**
Expand Down
276 changes: 276 additions & 0 deletions test/orm/base-model-options.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,53 @@ test.group('Model options | Model.firstOrSave', (group) => {
assert.deepEqual(user.$options!.profiler, client.profiler)
assert.deepEqual(user.$options!.connection, client.connectionName)
})

test('use transaction', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

await db.insertQuery().table('users').insert({ username: 'virk' })
const client = await db.connection('secondary').transaction()

const user = await User.firstOrSave({ username: 'virk' }, undefined, { client })
await client.commit()

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.deepEqual(user.$options!.profiler, client.profiler)
assert.deepEqual(user.$options!.connection, client.connectionName)
})

test('use transaction to save when search fails', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

const client = await db.connection('secondary').transaction()

const user = await User.firstOrSave({ username: 'virk' }, undefined, { client })
await client.rollback()

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 0)
assert.deepEqual(user.$options!.profiler, client.profiler)
assert.deepEqual(user.$options!.connection, client.connectionName)
})
})

test.group('Model options | Query Builder Preloads', (group) => {
Expand Down Expand Up @@ -1023,3 +1070,232 @@ test.group('Model options | Model Preloads', (group) => {
assert.deepEqual(user.profile.$sideloaded, { id: 2 })
})
})

test.group('Model options | Model.fetchOrCreateMany', (group) => {
group.before(async () => {
db = getDb()
BaseModel = getBaseModel(ormAdapter(db))
await setup()
})

group.after(async () => {
await cleanup()
await db.manager.closeAll()
})

group.afterEach(async () => {
await resetTables()
})

test('define custom connection', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

await db.insertQuery().table('users').insert({ username: 'virk' })

const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ connection: 'secondary' },
)

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.equal(user.$options!.connection, 'secondary')
assert.instanceOf(user.$options!.profiler, Profiler)
})

test('define custom connection when search fails', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ connection: 'secondary' },
)

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.equal(user.$options!.connection, 'secondary')
assert.instanceOf(user.$options!.profiler, Profiler)
})

test('define custom profiler', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

await db.insertQuery().table('users').insert({ username: 'virk' })
const profiler = new Profiler({})

const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ profiler },
)

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.equal(user.$options!.connection, 'primary')
assert.deepEqual(user.$options!.profiler, profiler)
})

test('define custom profiler when search fails', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

const profiler = new Profiler({})
const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ profiler },
)

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.equal(user.$options!.connection, 'primary')
assert.deepEqual(user.$options!.profiler, profiler)
})

test('define custom client', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

await db.insertQuery().table('users').insert({ username: 'virk' })
const client = db.connection('secondary')

const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ client },
)

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.deepEqual(user.$options!.profiler, client.profiler)
assert.deepEqual(user.$options!.connection, client.connectionName)
})

test('define custom client when search fails', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

const client = db.connection('secondary')

const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ client },
)

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.deepEqual(user.$options!.profiler, client.profiler)
assert.deepEqual(user.$options!.connection, client.connectionName)
})

test('use transaction', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

await db.insertQuery().table('users').insert({ username: 'virk' })
const client = await db.connection('secondary').transaction()

const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ client },
)
await client.commit()

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 1)
assert.isUndefined(user.$trx)
assert.deepEqual(user.$options!.profiler, client.profiler)
assert.deepEqual(user.$options!.connection, client.connectionName)
})

test('use transaction when search fails', async (assert) => {
class User extends BaseModel {
public static $table = 'users'

@column({ primary: true })
public id: number

@column()
public username: string
}

const client = await db.connection('secondary').transaction()

const [user] = await User.fetchOrCreateMany(
'username',
[{ username: 'virk' }],
{ client },
)
await client.rollback()

const total = await db.from('users').count('*', 'total')

assert.equal(total[0].total, 0)
assert.isUndefined(user.$trx)
assert.deepEqual(user.$options!.profiler, client.profiler)
assert.deepEqual(user.$options!.connection, client.connectionName)
})
})

0 comments on commit 45ea50e

Please sign in to comment.