メインコンテンツへスキップする

スキーマの生成

はじめに

ent.Schemaをプログラムで生成するツールの作成を容易にするために、ententgo.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.MutatorUpsertSchemaという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.goteam.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のごく一部がサポートされていません。サポートされていない機能の全リストはソースコードをご覧ください。