Generating Schemas
In order to manipulate an existing schema directory we must first load it into a schemast.Context
object:
To print back out our context to a target directory, use schemast.Print
:
package main
import (
"log"
"entgo.io/contrib/schemast"
)
func main() {
ctx, err := schemast.Load("./ent/schema")
if err != nil {
log.Fatalf("failed: %v", err)
}
// A no-op since we did not manipulate the Context at all.
if err := schemast.Print("./ent/schema"); err != nil {
log.Fatalf("failed: %v", err)
}
}
package schemast
// Mutator changes a Context.
type Mutator interface {
Mutate(ctx *Context) error
}
Currently, only a single type of schemast.Mutator
is implemented, UpsertSchema
:
To use it:
package main
"log"
"entgo.io/contrib/schemast"
"entgo.io/ent"
"entgo.io/ent/schema/field"
)
func main() {
ctx, err := schemast.Load("./ent/schema")
if err != nil {
log.Fatalf("failed: %v", err)
}
mutations := []schemast.Mutator{
&schemast.UpsertSchema{
Name: "User",
Fields: []ent.Field{
field.String("name"),
},
},
&schemast.UpsertSchema{
Name: "Team",
Fields: []ent.Field{
field.String("name"),
},
},
}
err = schemast.Mutate(ctx, mutations...)
if err := ctx.Print("./ent/schema"); err != nil {
log.Fatalf("failed: %v", err)
}
}
// user.go
package schema
"entgo.io/ent"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
type User struct {
ent.Schema
}
func (User) Fields() []ent.Field {
return []ent.Field{field.String("name")}
}
func (User) Edges() []ent.Edge {
return nil
}
func (User) Annotations() []schema.Annotation {
return nil
}
Edges are defined in ent
this way:
edge.To("edge_name", OtherSchema.Type)
This syntax relies on the fact that the OtherSchema
struct already exists when we define the edge so we can refer to its Type
method. When we are generating schemas programmatically, obviously we need somehow to describe the edge to the code-generator before the type definitions exist. To do this you can do something like:
type placeholder struct {
ent.Schema
}
func withType(e ent.Edge, typeName string) ent.Edge {
e.Descriptor().Type = typeName
return e
}
func newEdgeTo(edgeName, otherType string) ent.Edge {
// we pass a placeholder type to the edge constructor:
e := edge.To(edgeName, placeholder.Type)
// then we override the other type's name directly on the edge descriptor:
return withType(e, otherType)
}
schemast
is still experimental, APIs are subject to change in the future. In addition, a small portion of the definition API is unsupported at this point in time, to see a full list of unsupported features see the source code.