フック

オブジェクトのライフサイクル

フックとは、作成/クエリ/更新/削除の前後に呼び出される関数のことです。

モデルに特定のメソッドを定義した場合、作成、更新、クエリ、削除時に自動的に呼び出され、コールバックがエラーを返した場合、GORMは今後の操作を停止し、現在のトランザクションをロールバックします。

フックメソッドの型はfunc(*gorm.DB) errorである必要があります。

フック

オブジェクトの作成

作成に使用可能なフック

// begin transaction
BeforeSave
BeforeCreate
// save before associations
// insert into database
// save after associations
AfterCreate
AfterSave
// commit or rollback transaction

コード例

func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
u.UUID = uuid.New()

if !u.IsValid() {
err = errors.New("can't save invalid data")
}
return
}

func (u *User) AfterCreate(tx *gorm.DB) (err error) {
if u.ID == 1 {
tx.Model(u).Update("role", "admin")
}
return
}

注意 GORMでの保存/削除操作はデフォルトでトランザクション内で実行されるため、トランザクションがコミットされるまでそのトランザクションで行われた変更は表示されません。フックでエラーを返した場合、変更はロールバックされます。

func (u *User) AfterCreate(tx *gorm.DB) (err error) {
if !u.IsValid() {
return errors.New("rollback invalid user")
}
return nil
}

オブジェクトの更新

更新に使用可能なフック

// begin transaction
BeforeSave
BeforeUpdate
// save before associations
// update database
// save after associations
AfterUpdate
AfterSave
// commit or rollback transaction

コード例

func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
if u.readonly() {
err = errors.New("read only user")
}
return
}

// Updating data in same transaction
func (u *User) AfterUpdate(tx *gorm.DB) (err error) {
if u.Confirmed {
tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("verfied", true)
}
return
}

オブジェクトの削除

削除に使用可能なフック

// begin transaction
BeforeDelete
// delete from database
AfterDelete
// commit or rollback transaction

コード例

// Updating data in same transaction
func (u *User) AfterDelete(tx *gorm.DB) (err error) {
if u.Confirmed {
tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("invalid", false)
}
return
}

オブジェクトのクエリ

クエリに使用可能なフック

// load data from database
// Preloading (eager loading)
AfterFind

コード例

func (u *User) AfterFind(tx *gorm.DB) (err error) {
if u.MemberShip == "" {
u.MemberShip = "user"
}
return
}

現在の操作の変更

func (u *User) BeforeCreate(tx *gorm.DB) error {
// Modify current operation through tx.Statement, e.g:
tx.Statement.Select("Name", "Age")
tx.Statement.AddClause(clause.OnConflict{DoNothing: true})

// tx is new session mode with the `NewDB` option
// operations based on it will run inside same transaction but without any current conditions
var role Role
err := tx.First(&role, "name = ?", user.Role).Error
// SELECT * FROM roles WHERE name = "admin"
// ...
return err
}

プラチナスポンサー

ゴールドスポンサー

プラチナスポンサー

ゴールドスポンサー