Skip to Content

Models

The models package provides the BaseModelImpl struct that serves as the foundation for all GORM models in a Gofasta application. It includes UUID primary keys, automatic timestamp management, soft delete support, and optimistic locking via version fields.

Import

import "github.com/gofastadev/gofasta/pkg/models"

Key Types

BaseModel

The interface that all Gofasta models implement.

type BaseModel interface { GetID() string GetCreatedAt() time.Time GetUpdatedAt() time.Time GetDeletedAt() *time.Time GetVersion() int IsDeleted() bool }

BaseModelImpl

The concrete base struct to embed in all your GORM models.

type BaseModelImpl struct { ID string `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"` CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at,omitempty"` Version int `gorm:"default:1" json:"version"` }

Key Functions

FunctionSignatureDescription
GetIDfunc (b *BaseModelImpl) GetID() stringReturns the model’s UUID
GetCreatedAtfunc (b *BaseModelImpl) GetCreatedAt() time.TimeReturns the creation timestamp
GetUpdatedAtfunc (b *BaseModelImpl) GetUpdatedAt() time.TimeReturns the last update timestamp
GetDeletedAtfunc (b *BaseModelImpl) GetDeletedAt() *time.TimeReturns the soft-delete timestamp, or nil
GetVersionfunc (b *BaseModelImpl) GetVersion() intReturns the current version for optimistic locking
IsDeletedfunc (b *BaseModelImpl) IsDeleted() boolReturns true if the model is soft-deleted
BeforeCreatefunc (b *BaseModelImpl) BeforeCreate(tx *gorm.DB) errorGORM hook that generates a UUID before insert

Usage

Defining a Model

Embed BaseModelImpl in your domain models to inherit UUID, timestamps, soft delete, and versioning.

type User struct { models.BaseModelImpl Name string `gorm:"type:varchar(255);not null" json:"name"` Email string `gorm:"type:varchar(255);uniqueIndex;not null" json:"email"` Password string `gorm:"type:varchar(255);not null" json:"-"` Role string `gorm:"type:varchar(50);default:'user'" json:"role"` } type Post struct { models.BaseModelImpl Title string `gorm:"type:varchar(255);not null" json:"title"` Content string `gorm:"type:text" json:"content"` AuthorID string `gorm:"type:uuid;not null" json:"author_id"` Author User `gorm:"foreignKey:AuthorID" json:"author,omitempty"` }

Automatic UUID Generation

The BeforeCreate hook automatically generates a UUID v4 for new records.

user := User{Name: "Jane", Email: "jane@example.com"} db.Create(&user) fmt.Println(user.ID) // "f47ac10b-58cc-4372-a567-0e02b2c3d479"

Soft Delete

GORM’s soft delete is built in. Calling Delete sets deleted_at instead of removing the row.

// Soft delete db.Delete(&user) fmt.Println(user.IsDeleted()) // true // Query excludes soft-deleted records by default db.Find(&users) // only returns non-deleted users // Include soft-deleted records db.Unscoped().Find(&users) // returns all users // Permanently delete db.Unscoped().Delete(&user)

Optimistic Locking

Use the Version field to prevent lost updates in concurrent scenarios.

func (r *UserRepository) Update(ctx context.Context, user *User) error { result := r.db.Model(user). Where("version = ?", user.Version). Updates(map[string]interface{}{ "name": user.Name, "email": user.Email, "version": user.Version + 1, }) if result.RowsAffected == 0 { return errors.New("CONFLICT", "record was modified by another request", 409) } return result.Error }

Auto-Migration

db, err := config.SetupDBWithMigrate(cfg.Database, &User{}, &Post{})
  • Config — Database setup and connection
  • Seeds — Seed initial data for models
  • Types — Shared type definitions
Last updated on