Embedded structs and mixins
A struct can group columns without being a table of its own. A mixin is one that brings its configuration along with it.
Anonymous embedding
The embedded struct's fields become the model's columns, the same way ant.Base works.
type Audit struct {
CreatedBy string
}
type Shop struct {
Audit
ID int64
Name string
}
Named groups, with a prefix
The embedded tag does the same for a named field, and prefix keeps two of them apart.
type Address struct {
City string
Zip string
}
type Shop struct {
ID int64
Billing Address `ant:"embedded,prefix=billing_"`
Shipping Address `ant:"embedded,prefix=shipping_"`
}
var S = ant.Fields[Shop]()
oslo, err := db.Shops.Where(ant.Eq(&S.Shipping.City, "Oslo")).All(ctx)
That table has billing_city, billing_zip, shipping_city, and shipping_zip. Tracking works per column, so changing Billing.Zip writes one column. Embedding nests too.
Mixins
A mixin is an embedded struct with a ConfigureMixin method. It works by column name, without knowing who embeds it, which suits anything many models share.
type Created struct {
Created int64
}
func (Created) ConfigureMixin(m *ant.Mixin) {
m.Index("created").Name(m.Table() + "_created_idx")
m.Check(m.Table()+"_created_positive", "created >= 0")
}
type Event struct {
ID int64
Created
}
A mixin can add a global filter too, which is how multi-tenancy stays impossible to forget. A hook method on the mixin is promoted to every model that embeds it.
See it tested: tests/features/model_definition/embedded_test.go