Skip to main content

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.