gormtables

command module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 14 Imported by: 0

README

gormtables

中文文档

gormtables is a code-generation tool that scans your GORM model packages, resolves the foreign-key dependencies between models, and emits an ordered Go slice for use with db.AutoMigrate.

go install github.com/hr3lxphr6j/gormtables@latest

Why?

gorm.AutoMigrate accepts a variadic list of model pointers and creates (or alters) the corresponding tables. When your models have foreign-key constraints the order matters: the referenced table must exist before the referencing table can add its constraint.

Maintaining that order by hand is error-prone. gormtables derives the correct order automatically by reading the gorm:"foreignKey:…" struct tags and topologically sorting the models. The output is a plain Go source file that is easy to review and diff in pull requests.


Dependency semantics

Ordering follows one rule: the table that carries the foreign-key column must be created after the table it points at. Both association directions are read, because either one can put the FK on either table.

A gorm:"foreignKey:<FK>" tag is classified by where <FK> lives:

<FK> is a field of Association Which table gets the FK Edge
the struct declaring the tag BelongsTo that same struct it depends on the referenced type
the referenced struct HasMany / HasOne the referenced struct the referenced type depends on the declaring one

The HasMany/HasOne row is easy to get backwards. The FK column does live in the other table — but that is exactly why it constrains ordering: GORM copies the relation onto the referenced schema, so CREATE TABLE for the child emits the FK inline and the parent has to exist by then.

Skipped, in both directions:

  • constraint:- — GORM builds no FK, so there is nothing to order.
  • Self-references (tree structures) — a FK pointing at the table being created is satisfied by that same statement.
  • many2many — GORM materialises the join table and orders it itself.

Cycles among two or more models are reported as an error naming the structs involved. Declaring one association from both sides is not a cycle: the same edge is simply discovered twice and collapsed, matching GORM, which emits a single FK for such a pair.

Given these declarations:

type User struct {
    BaseModel
    Comments []Comment `gorm:"foreignKey:AuthorID"` // HasMany  → FK on comments
}

type Post struct {
    BaseModel
    UserID uint64
    User   *User `gorm:"foreignKey:UserID"`         // BelongsTo → FK on posts
}

type Comment struct {
    BaseModel
    PostID   uint64
    AuthorID uint64
    Post     *Post `gorm:"foreignKey:PostID"`       // BelongsTo → FK on comments
}

the tables holding a FK are posts (→ users) and comments (→ users, posts):

graph LR
    posts -->|FK| users
    comments -->|FK| users
    comments -->|FK| posts

gormtables produces User → Post → Comment, so AutoMigrate creates users first, then posts, then comments — each table arriving after everything its own foreign keys reference.


Opt-in / opt-out rules

A struct is included if it satisfies at least one of:

Rule Example
Anonymously embeds a base struct listed in -base BaseModel (default) or gorm.Model
Carries the enable marker comment (see -enable-marker) // AutoMigrate:enable

A struct is excluded (regardless of the above) if it carries the disable marker comment (see -disable-marker):

// AutoMigrate:disable
type Draft struct {
    BaseModel
    Body string
}

Usage

go:generate
//go:generate gormtables -models ./internal/model -out ./internal/db/tables.go

Then run:

go generate ./internal/db/...
Command line
gormtables \
  -models ./internal/model \
  -out    ./internal/db/tables.go \
  -pkg    database \
  -var    autoMigrateTables
Generated output example

Given models:

// internal/model/user.go
type User struct {
    BaseModel
    Name string
}

// internal/model/post.go
type Post struct {
    BaseModel
    UserID uint64
    User   *User `gorm:"foreignKey:UserID"`
    Title  string
}

gormtables generates:

// Code generated by gormtables; DO NOT EDIT.

package database

import (
    model "example.com/app/internal/model"
)

// autoMigrateTables is the ordered list of GORM models for AutoMigrate.
// Referenced tables appear earlier in the slice, so that by the time a table
// with a foreign key is created the table it points at already exists.
var autoMigrateTables = []any{
    &model.User{},
    &model.Post{},
}

Plug it in:

if err := db.AutoMigrate(autoMigrateTables...); err != nil {
    log.Fatal(err)
}

Flag reference

Flag Default Description
-models (required) Comma-separated list of model directories to scan
-out (required) Output file path
-pkg database Package name written in the generated file
-var autoMigrateTables Name of the generated []any variable
-base BaseModel,gorm.Model Comma-separated base-embed names that qualify a struct
-enable-marker AutoMigrate:enable Comment text that force-includes a struct
-disable-marker AutoMigrate:disable Comment text that force-excludes a struct
-tag gorm Struct-tag key used for foreign-key inspection

Tests

go test ./...                    # generator: scanning, sorting, output

Ordering also has to hold against a real database, which no amount of unit testing can establish. integration/ migrates fixtures covering the common association shapes against MySQL and PostgreSQL:

docker compose -f integration/docker-compose.yml up -d --wait
go test -C integration ./...

It is a separate module so that installing the generator stays free of GORM and database drivers. See integration/README.md for the fixture groups and how to add one.


License

MIT — see LICENSE.

Documentation

Overview

gormtables scans one or more GORM model packages and generates an ordered Go source file that declares the AutoMigrate table list.

Usage:

gormtables -models ./internal/model -out ./internal/db/tables.go

See README.md for full flag documentation and examples.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL