Skip to main content

Configure

Conventions and a few tags cover most models. When they don't, Configure is an optional method where you override them in typed Go. It runs once, when a context containing the model opens.

The method​

type Plan struct {
Slug string
Title string
}

func (Plan) Configure(b *ant.ModelBuilder[Plan]) {
b.Table("pricing_plans")
b.Key(&Pl.Slug)
}

var Pl = ant.Fields[Plan]()
Mistakes stop Open

An empty table name, a relation used as a key, or a probe from another model all fail as soon as the database opens, so you find out at startup, not in the middle of production traffic.

Columns​

b.Column describes what the database column looks like. It matters to migrations, not to queries.

func (Article) Configure(b *ant.ModelBuilder[Article]) {
b.Column(&A.Title).Length(200) // varchar(200)
b.Column(&A.Price).Precision(10, 2) // numeric(10,2)
b.Column(&A.Code).Fixed(4) // char(4)
b.Column(&A.Status).Type("post_status") // any SQL type
b.Column(&A.Views).Default("0") // a SQL expression
b.Column(&A.Note).Nullable() // or NotNull()
b.Column(&A.Slug).Collation("C").Unique()
b.Column(&A.Search).Generated("to_tsvector('english', title)")
b.Column(&A.Secret).Comment("Never shown").Sensitive()
}

A native enum and a table comment:

func (Article) Configure(b *ant.ModelBuilder[Article]) {
b.Column(&A.Status).Enum("post_status", "draft", "live")
b.Comment("Published articles")
}

Indexes​

func (Article) Configure(b *ant.ModelBuilder[Article]) {
b.Index(&A.AuthorID).And(&A.CreatedAt).Desc() // composite, descending
b.Index(&A.Slug).Unique()
b.Index(&A.Published).Where("deleted_at IS NULL").Name("posts_live_idx")
b.Index(&A.Tags).Using("gin")
b.IndexExpr("lower(title)").Name("posts_title_lower_idx")
b.Index(&A.Body).Include(&A.Title).Concurrently()
}

.Concurrently() makes the migration run outside a transaction, so the index builds without blocking writes.

Check constraints​

func (Article) Configure(b *ant.ModelBuilder[Article]) {
b.Check("articles_views_positive", "views >= 0")
}

Relations​

Configure is also where you declare relations that names can't find. See declaring relations.

Everything else​

Configure is home to everything else a model can say about itself:

CallPage
b.Key, b.CompositeKey, b.NoKey, b.KeyNameKeys
b.Discriminator, b.View, b.SchemaShared tables and views
b.FilterGlobal filters
b.ValidateValidation
b.ComparerSaveChanges
b.NoTimestampsTimestamps
b.PartitionByRange, b.PartitionByList, b.PartitionByHashPartitioned tables
b.ExcludeFromMigrationsModels to tables