スキーマの生成
はじめに
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のごく一部がサポートされていません。サポートされていない機能の全リストはソースコードをご覧ください。