スキーマの生成
はじめに
ent.Schemaをプログラムで生成するツールの作成を容易にするために、entはentgo.io/contrib/schemastパッケージを使用したschema/ディレクトリの操作をサポートしています。
API
Loading
既存のschemaディレクトリを操作するには、最初に schemast.Context オブジェクトにロードする必要があります:
package main
import (
"fmt"
"log"
"entgo.io/contrib/schemast"
)
func main() {
ctx, err := schemast.Load("./ent/schema")
if err != nil {
log.Fatalf("failed: %v", err)
}
if ctx.HasType("user") {
fmt.Println("schema directory contains a schema named User!")
}
}
Printing
コンテキストをターゲットディレクトリに戻すには、 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)
}
// コンテキストを全く操作していないので、問題ありません
if err := schemast.Print("./ent/schema"); err != nil {
log.Fatalf("failed: %v", err)
}
}
Mutators
ent/schemaディレクトリをコード上から変更するためにschemast.Mutateを使用できます。これは、コンテキストに適用するschemast.Mutatorのリストを受け取ります:
package schemast
// Mutatorはコンテキストを変更します
type Mutator interface {
Mutate(ctx *Context) error
}
現在実装されているschemast.MutatorはUpsertSchemaという1種類のみです。
package schemast
// UpsertSchemaはMutatorの実装です。 UpsertSchemaは、Nameと同じ名前の型が存在しない場合はContextに追加し、
// その型のFields、Edges、Indexes、Annotationsメソッドを書き換えます。
type UpsertSchema struct {
Name string
Fields []ent.Field
Edges []ent.Edge
Indexes []ent.Index
Annotations []schema.Annotation
}
使用するには:
package main
import (
"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)
}
}
このプログラムを実行した後、schemaディレクトリ内に2つの新しいファイルが存在することを確認します:user.go と team.go:
// user.go
package schema
import (
"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
}
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
)
type Team struct {
ent.Schema
}
func (Team) Fields() []ent.Field {
return []ent.Field{field.String("name")}
}
func (Team) Edges() []ent.Edge {
return nil
}
func (Team) Annotations() []schema.Annotation {
return nil
}
エッジの使い方
エッジは次のように ent で定義されます:
edge.To("edge_name", OtherSchema.Type)
この構文は、エッジを定義したときにOtherSchema構造体がすでに存在していて、そのTypeメソッドを参照できるという事実に依存しています。 プログラムでスキーマを生成している場合、当然ながら、型定義が存在する前にコードジェネレーターにエッジを何らかの形で記述する必要があります。 そのためには、次のようにします:
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 {
// エッジのコンストラクタにプレースホルダ型を渡しています
e := edge.To(edgeName, placeholder.Type)
// これで、エッジ記述子に直接、他の型の名前を上書きします:
return withType(e, otherType)
}
使用例
protoc-gen-ent (doc)はプログラムで.protoファイルからent.Schemaを生成するprotocプラグインで、schemastを使ってターゲットの schema を操作します。 どのように行っているかを知るには、ソースコード を読んでください。
注意事項
schemastはまだ実験段階であり、APIは将来的に変更される可能性があります。 また、現時点ではent.Field定義のAPIのごく一部がサポートされていません。サポートされていない機能の全リストはソースコードをご覧ください。