Skip to content

Instantly share code, notes, and snippets.

@jarifibrahim
Last active February 9, 2024 16:37
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jarifibrahim/039090459ff04e14233dccd52ee2d9cf to your computer and use it in GitHub Desktop.
Save jarifibrahim/039090459ff04e14233dccd52ee2d9cf to your computer and use it in GitHub Desktop.
Database cleanup hook using GORM
// DeleteCreatedEntities sets up GORM `onCreate` hook and return a function that can be deferred to
// remove all the entities created after the hook was set up
// You can use it as
//
// func TestSomething(t *testing.T){
// db, _ := gorm.Open(...)
//
// cleaner := DeleteCreatedEntities(db)
// defer cleaner()
//
// }
func DeleteCreatedEntities(db *gorm.DB) func() {
type entity struct {
table string
keyname string
key interface{}
}
var entries []entity
hookName := "cleanupHook"
db.Callback().Create().After("gorm:create").Register(hookName, func(scope *gorm.Scope) {
fmt.Printf("Inserted entities of %s with %s=%v\n", scope.TableName(), scope.PrimaryKey(), scope.PrimaryKeyValue())
entries = append(entries, entity{table: scope.TableName(), keyname: scope.PrimaryKey(), key: scope.PrimaryKeyValue()})
})
return func() {
// Remove the hook once we're done
defer db.Callback().Create().Remove(hookName)
// Find out if the current db object is already a transaction
_, inTransaction := db.CommonDB().(*sql.Tx)
tx := db
if !inTransaction {
tx = db.Begin()
}
// Loop from the end. It is important that we delete the entries in the
// reverse order of their insertion
for i := len(entries) - 1; i >= 0; i-- {
entry := entries[i]
fmt.Printf("Deleting entities from '%s' table with key %v\n", entry.table, entry.key)
tx.Table(entry.table).Where(entry.keyname+" = ?", entry.key).Delete("")
}
if !inTransaction {
tx.Commit()
}
}
}
@damif94
Copy link

damif94 commented Mar 24, 2023

can this be updated to current version of gorm?

@lundha
Copy link

lundha commented Oct 17, 2023

db.Callback().Create().After("gorm:create").Register(hookName, func(db *gorm.DB) {
		field := db.Statement.Schema.PrioritizedPrimaryField
		fieldValue, isZero := field.ValueOf(db.Statement.Context, db.Statement.ReflectValue)
		if isZero {
			fmt.Printf("field %s is zero\n", field.Name)
			return
		}
		fmt.Printf("Inserted entities of %s with %v=%v\n", db.Statement.Table, field.Name, fieldValue)
		entries = append(entries, entity{table: db.Statement.Table, key: field.Name, value: fieldValue})
})

This should work with the current version

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment