Home >Backend Development >Golang >Golang GORM implements archived_at similar to soft deletion

Golang GORM implements archived_at similar to soft deletion

WBOY
WBOYforward
2024-02-05 22:33:12486browse

Golang GORM 实现类似于软删除的archived_at

Question content

I am using GORM V1. I have a requirement where we want to add a archived_at column similar to GORM deleted_at. Entities can be archived and unarchived, and by default we want to query records with archived_at being NULL.

My current idea is to use GORM callbacks to register callbacks

  1. Register the callback before the gorm:query callback.
  2. Check if the schema/model requires the archived_at field.
  3. If this field does exist, please add the necessary conditions.

This sounds great, but how do I efficiently copy the equivalent of the archive's Unscoped() .

  • What is the idiomatic way to get archived records? How do I indicate whether the archived_at column should be added to the necessary callback?
  • I also run into a situation where I just want to get archived records (where archived_at IS NOT NULL).

Edit - My use case is to use both the deleted_at and archived_at fields, rather than using one field instead of the other. I want to keep the ability to soft delete while adding the ability to archive entities. The user may simply be archived and then possibly deleted (soft deleted).


Correct Answer


Invite feedback. This is what I'm thinking of right now.

Callback.go

package db

import (
    "fmt"
    "reflect"

    "gorm.io/gorm"
)

const (
    gormsettingkeyunscopearchive = "unscope_archive"
    structfieldnamearchivedat    = "archivedat"
)

// archivedquerycallback - conditionally adds "where archived_at is null" if the model being queried has the following
// 1. struct field represented by structfieldnamearchivedat
// 2. gorm instance setting gormsettingkeyunscopearchive, see unscopearchive
func archivedquerycallback(db *gorm.db) {
    // check if model is a pointer and has an indirect struct type
    if db.statement.model != nil &&
        reflect.typeof(db.statement.model).kind() == reflect.ptr &&
        reflect.indirect(reflect.valueof(db.statement.model)).kind() == reflect.struct {
        stmt := &gorm.statement{db: db}
        parseerr := stmt.parse(db.statement.model)
        if parseerr != nil {
            panic(parseerr)
        }

        if _, archivedatexists := stmt.schema.fieldsbyname[structfieldnamearchivedat]; archivedatexists {
            v, ok := db.instanceget(gormsettingkeyunscopearchive)
            if ok {
                if v == true {
                    return
                }
            }

            db.where(fmt.sprintf("%s is null", stmt.schema.fieldsbyname[structfieldnamearchivedat].dbname))
        }
    }
}

scope.go

// unscopearchive - sets a true value for the key gormsettingkeyunscopearchive
func unscopearchive(db *gorm.db) *gorm.db {
    db = db.instanceset(gormsettingkeyunscopearchive, true)

    return db
}

main.go

   type User {
       ID           string         `gorm:"primary_key" json:"id" valid:"uuidv4, optional"`
    CreatedAt    time.Time      `valid:"-" json:"created_at"`
    UpdatedAt    time.Time      `valid:"-" json:"-"`
    DeletedAt    gorm.DeletedAt `sql:"index" valid:"-" json:"-"`
    ArchivedAt   time.Time
   }

   var user []User
   ctx := context.Background()
   dbClient := InitializeGORM() //helper 
   _ := dbClient.WithContext(ctx).Find(&user).Error // SELECT * FROM users WHERE deleted_at IS NULL AND archived_at IS NULL;

   _ := dbClient.WithContext(ctx).Scopes(UnscopeArchive).Find(&user).Error // SELECT * FROM users WHERE deleted_at IS NULL;

The above is the detailed content of Golang GORM implements archived_at similar to soft deletion. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete