diff --git a/adonis-typings/model.ts b/adonis-typings/model.ts index 7b7c22d0..e0e837b3 100644 --- a/adonis-typings/model.ts +++ b/adonis-typings/model.ts @@ -480,9 +480,9 @@ declare module '@ioc:Adonis/Lucid/Model' { $consumeAdapterResult (adapterResult: ModelObject, sideloadAttributes?: ModelObject): void $hydrateOriginals(): void - fill (value: Partial>, allowNonExtraProperties?: boolean): void - merge (value: Partial>, allowNonExtraProperties?: boolean): void - save (): Promise + fill (value: Partial>, allowNonExtraProperties?: boolean): this + merge (value: Partial>, allowNonExtraProperties?: boolean): this + save (): Promise delete (): Promise refresh (): Promise preload: ModelBuilderPreloadFn diff --git a/src/Orm/BaseModel/index.ts b/src/Orm/BaseModel/index.ts index 3fdf566a..a24b2827 100644 --- a/src/Orm/BaseModel/index.ts +++ b/src/Orm/BaseModel/index.ts @@ -1413,10 +1413,11 @@ export class BaseModel implements LucidRow { * fill isn't allowed, since we disallow setting relationships * locally */ - public fill (values: any, allowNonExtraProperties: boolean = false) { + public fill (values: any, allowNonExtraProperties: boolean = false): this { this.$attributes = {} this.merge(values, allowNonExtraProperties) this.fillInvoked = true + return this } /** @@ -1425,7 +1426,7 @@ export class BaseModel implements LucidRow { * 1. If key is unknown, it will be added to the `extras` object. * 2. If key is defined as a relationship, it will be ignored and one must call `$setRelated`. */ - public merge (values: any, allowNonExtraProperties: boolean = false) { + public merge (values: any, allowNonExtraProperties: boolean = false): this { const Model = this.constructor as typeof BaseModel /** @@ -1474,6 +1475,8 @@ export class BaseModel implements LucidRow { this.$extras[key] = value }) } + + return this } /** @@ -1498,7 +1501,7 @@ export class BaseModel implements LucidRow { /** * Perform save on the model instance to commit mutations. */ - public async save () { + public async save (): Promise { this.ensureIsntDeleted() const Model = this.constructor as typeof BaseModel @@ -1517,7 +1520,7 @@ export class BaseModel implements LucidRow { await Model.$hooks.exec('after', 'create', this) await Model.$hooks.exec('after', 'save', this) - return + return this } /** @@ -1532,7 +1535,7 @@ export class BaseModel implements LucidRow { * Do not issue updates when model doesn't have any mutations */ if (!this.$isDirty) { - return + return this } /** @@ -1545,6 +1548,7 @@ export class BaseModel implements LucidRow { await Model.$hooks.exec('after', 'update', this) await Model.$hooks.exec('after', 'save', this) + return this } /** diff --git a/test/orm/base-model.spec.ts b/test/orm/base-model.spec.ts index fdef8bdc..c20b463a 100644 --- a/test/orm/base-model.spec.ts +++ b/test/orm/base-model.spec.ts @@ -62,6 +62,61 @@ test.group('Base model | boot', (group) => { await db.manager.closeAll() }) + test('ensure save method is chainable', async (assert) => { + const adapter = new FakeAdapter() + class User extends BaseModel { + @column() + public username: string + + @column() + public age: number + } + User.$adapter = adapter + + const user = new User() + user.username = 'virk' + user.age = 22 + const chained = await user.save() + + assert.instanceOf(chained, User) + }) + + test('ensure fill method is chainable', async (assert) => { + class User extends BaseModel { + @column() + public username: string + + @column() + public age: number + } + + const user = new User() + const chained = user.fill({ + username: 'virk', + age: 22, + }) + + assert.instanceOf(chained, User) + }) + + test('ensure merge method is chainable', async (assert) => { + class User extends BaseModel { + @column() + public username: string + + @column() + public age: number + } + + const user = new User() + const chained = user.merge({ + username: 'virk', + age: 22, + }) + + assert.instanceOf(chained, User) + }) + test('compute table name from model name', async (assert) => { class User extends BaseModel { @column({ isPrimary: true })