entc/load: add support for embedding schemas

Reviewed By: alexsn

Differential Revision: D16884402

fbshipit-source-id: 216bbf875251b0cbdd61e312ad763b439cab7813
This commit is contained in:
Ariel Mashraki
2019-08-18 04:28:49 -07:00
committed by Facebook Github Bot
parent 7800c20154
commit ba950aac52
8 changed files with 80 additions and 26 deletions

File diff suppressed because one or more lines are too long

View File

@@ -89,7 +89,7 @@ func (c *Config) Load() (*SchemaSpec, error) {
func (c *Config) load() (string, error) {
// get the ent package info statically instead of dealing with string constants
// in the code, since import is handled by goimports and renaming should be easy.
entface := reflect.TypeOf(struct{ ent.Schema }{}).Field(0).Type
entface := reflect.TypeOf(struct{ ent.Interface }{}).Field(0).Type
pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax}, c.Path, entface.PkgPath())
if err != nil {
return "", err

View File

@@ -3,6 +3,8 @@ package load
import (
"testing"
"fbc/ent/schema/field"
"github.com/stretchr/testify/require"
)
@@ -39,7 +41,21 @@ func TestLoadNoSchema(t *testing.T) {
func TestLoadSchemaFailure(t *testing.T) {
cfg := &Config{Path: "./testdata/failure"}
schemas, err := cfg.Load()
spec, err := cfg.Load()
require.Error(t, err)
require.Empty(t, schemas)
require.Nil(t, spec)
}
func TestLoadBaseSchema(t *testing.T) {
cfg := &Config{Path: "./testdata/base"}
spec, err := cfg.Load()
require.NoError(t, err)
require.Len(t, spec.Schemas, 1)
require.Len(t, spec.Schemas[0].Fields, 2, "embedded base schema")
f1 := spec.Schemas[0].Fields[0]
require.Equal(t, "base_field", f1.Name)
require.Equal(t, field.TypeInt, f1.Type)
f2 := spec.Schemas[0].Fields[1]
require.Equal(t, "user_field", f2.Name)
require.Equal(t, field.TypeString, f2.Type)
}

View File

@@ -70,7 +70,7 @@ func NewEdge(e ent.Edge) *Edge {
// MarshalSchema encode the ent.Schema interface into a JSON
// that can be decoded into the Schema object object.
func MarshalSchema(schema ent.Schema) (b []byte, err error) {
func MarshalSchema(schema ent.Interface) (b []byte, err error) {
s := &Schema{Name: indirect(reflect.TypeOf(schema)).Name()}
fields, err := safeFields(schema)
if err != nil {
@@ -120,7 +120,7 @@ func MarshalSchema(schema ent.Schema) (b []byte, err error) {
}
// safeFields wraps the schema.Fields method with recover to ensure no panics in marshaling.
func safeFields(schema ent.Schema) (fields []ent.Field, err error) {
func safeFields(schema ent.Interface) (fields []ent.Field, err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("schema.Fields panics: %v", v)
@@ -131,7 +131,7 @@ func safeFields(schema ent.Schema) (fields []ent.Field, err error) {
}
// safeEdges wraps the schema.Edges method with recover to ensure no panics in marshaling.
func safeEdges(schema ent.Schema) (edges []ent.Edge, err error) {
func safeEdges(schema ent.Interface) (edges []ent.Edge, err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("schema.Edges panics: %v", v)
@@ -142,7 +142,7 @@ func safeEdges(schema ent.Schema) (edges []ent.Edge, err error) {
}
// safeIndexes wraps the schema.Indexes method with recover to ensure no panics in marshaling.
func safeIndexes(schema ent.Schema) (indexes []ent.Index, err error) {
func safeIndexes(schema ent.Interface) (indexes []ent.Index, err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("schema.Indexes panics: %v", v)

View File

@@ -60,7 +60,7 @@ func (Group) Edges() []ent.Edge {
}
func TestMarshalSchema(t *testing.T) {
for _, u := range []ent.Schema{User{}, &User{}} {
for _, u := range []ent.Interface{User{}, &User{}} {
buf, err := MarshalSchema(u)
require.NoError(t, err)

View File

@@ -12,9 +12,9 @@ import (
{{ $base := base .Package}}
var schemas = []ent.Schema{
var schemas = []ent.Interface{
{{ range $_, $name := .Names }}
{{- $base }}.{{- printf "%s{Schema: ent.DefaultSchema}" $name }},
{{- $base }}.{{- printf "%s{}" $name }},
{{ end -}}
}

29
entc/load/testdata/base/schema.go vendored Normal file
View File

@@ -0,0 +1,29 @@
package base
import (
"fbc/ent"
"fbc/ent/schema/field"
)
// base schema for sharing fields and edges.
type base struct {
ent.Schema
}
func (base) Fields() []ent.Field {
return []ent.Field{
field.Int("base_field"),
}
}
// User holds the user schema.
type User struct {
base
}
func (u User) Fields() []ent.Field {
return append(
u.base.Fields(),
field.String("user_field"),
)
}