Models are Go structs that map to database tables using GORM. They live in app/models/.
catuaba g model Product name:string price:float description:text active:booleanThis creates two files:
app/models/product.go— the Go structdatabase/migrations/<timestamp>_create_products.up.sql— SQL to create the tabledatabase/migrations/<timestamp>_create_products.down.sql— SQL to drop the table
package models
import "gorm.io/gorm"
type Product struct {
gorm.Model
Name string `json:"name"`
Price float64 `json:"price"`
Description string `json:"description"`
Active bool `json:"active"`
}gorm.Model embeds ID, CreatedAt, UpdatedAt, and DeletedAt (soft delete).
| CLI type | Go type | SQL type | Example |
|---|---|---|---|
string |
string |
VARCHAR(255) |
name:string |
text |
string |
TEXT |
bio:text |
integer |
int |
INTEGER |
age:integer |
float |
float64 |
REAL |
price:float |
boolean |
bool |
BOOLEAN |
active:boolean |
datetime |
time.Time |
TIMESTAMP |
published_at:datetime |
Models are queried through the database.DB global (a *gorm.DB instance):
// Find all
var products []models.Product
database.DB.Find(&products)
// Find by ID
var product models.Product
database.DB.First(&product, 1)
// Where clause
database.DB.Where("active = ?", true).Find(&products)
// Pagination
database.DB.Offset(0).Limit(20).Find(&products)
// Count
var count int64
database.DB.Model(&models.Product{}).Count(&count)
// Create
product := models.Product{Name: "Widget", Price: 9.99}
database.DB.Create(&product)
// Update
database.DB.Save(&product)
// Delete (soft delete — sets deleted_at)
database.DB.Delete(&product)GORM supports all standard relationships. Add them manually to your model:
// app/models/post.go
type Post struct {
gorm.Model
Title string `json:"title"`
Body string `json:"body"`
CategoryID uint `json:"category_id"`
Category Category `json:"category" gorm:"foreignKey:CategoryID"`
Tags []Tag `json:"tags" gorm:"many2many:post_tags;"`
}
// app/models/category.go
type Category struct {
gorm.Model
Name string `json:"name"`
Posts []Post `json:"posts"`
}Eager-loading:
database.DB.Preload("Category").Preload("Tags").Find(&posts)Catuaba uses raw SQL migrations (not AutoMigrate). Each model generator creates paired up/down files:
-- database/migrations/20240101120000_create_products.up.sql
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(255) NOT NULL DEFAULT '',
price REAL NOT NULL DEFAULT 0,
description TEXT NOT NULL DEFAULT '',
active BOOLEAN NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- database/migrations/20240101120000_create_products.down.sql
DROP TABLE IF EXISTS products;Run migrations:
catuaba db migrate # Run all pending
catuaba db rollback # Rollback last
catuaba db status # Show statusCreate a manual migration (e.g., adding an index):
catuaba g migration add_index_to_products_nameThen edit the generated SQL files manually.