mirror of
https://github.com/ent/ent.git
synced 2026-04-28 05:30:56 +03:00
ent: support external uuid types (#181)
Summary: Pull Request resolved: https://github.com/facebookincubator/ent/pull/181 The lack of generic typing requires to check the function type in the "loading" phase of the schema. Reviewed By: alexsn Differential Revision: D18636969 fbshipit-source-id: d8229779bf3c2490e51f5d0d4c550c70e2cd2550
This commit is contained in:
committed by
Facebook Github Bot
parent
e54373f410
commit
1e49561634
File diff suppressed because one or more lines are too long
@@ -115,6 +115,12 @@ func NewField(fd *field.Descriptor) (*Field, error) {
|
||||
if _, err := json.Marshal(fd.Default); err == nil {
|
||||
sf.DefaultValue = fd.Default
|
||||
}
|
||||
if fd.Info.Type == field.TypeUUID && fd.Default != nil {
|
||||
typ := reflect.TypeOf(fd.Default)
|
||||
if typ.Kind() != reflect.Func || typ.NumIn() != 0 || typ.NumOut() != 1 || typ.Out(0).String() != fd.Info.String() {
|
||||
return nil, fmt.Errorf("expect type (func() %s) for uuid default value", fd.Info.String())
|
||||
}
|
||||
}
|
||||
return sf, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/facebookincubator/ent/schema/field"
|
||||
"github.com/facebookincubator/ent/schema/index"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -38,6 +39,8 @@ func (User) Fields() []ent.Field {
|
||||
Sensitive(),
|
||||
field.Time("creation_time").
|
||||
Default(time.Now),
|
||||
field.UUID("uuid", uuid.UUID{}).
|
||||
Default(uuid.New),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +82,7 @@ func TestMarshalSchema(t *testing.T) {
|
||||
schema := &Schema{}
|
||||
require.NoError(t, json.Unmarshal(buf, schema))
|
||||
require.Equal(t, "User", schema.Name)
|
||||
require.Len(t, schema.Fields, 7)
|
||||
require.Len(t, schema.Fields, 8)
|
||||
require.Equal(t, "age", schema.Fields[0].Name)
|
||||
require.Equal(t, field.TypeInt, schema.Fields[0].Info.Type)
|
||||
|
||||
@@ -110,6 +113,10 @@ func TestMarshalSchema(t *testing.T) {
|
||||
require.Equal(t, field.TypeTime, schema.Fields[6].Info.Type)
|
||||
require.Nil(t, schema.Fields[6].DefaultValue)
|
||||
|
||||
require.Equal(t, "uuid", schema.Fields[7].Name)
|
||||
require.Equal(t, field.TypeUUID, schema.Fields[7].Info.Type)
|
||||
require.True(t, schema.Fields[7].Default)
|
||||
|
||||
require.Len(t, schema.Edges, 2)
|
||||
require.Equal(t, "groups", schema.Edges[0].Name)
|
||||
require.Equal(t, "Group", schema.Edges[0].Type)
|
||||
@@ -129,22 +136,38 @@ func TestMarshalSchema(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type Invalid struct {
|
||||
type InvalidEdge struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
// Edge panics because the edge declaration is invalid.
|
||||
func (Invalid) Edges() []ent.Edge {
|
||||
func (InvalidEdge) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("invalid", Invalid{}.Type),
|
||||
edge.From("invalid", InvalidEdge{}.Type),
|
||||
}
|
||||
}
|
||||
|
||||
type InvalidUUID struct {
|
||||
ent.Schema
|
||||
}
|
||||
|
||||
func (InvalidUUID) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.UUID("invalid", uuid.New()).
|
||||
Default(time.Now),
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalFails(t *testing.T) {
|
||||
i := Invalid{}
|
||||
buf, err := MarshalSchema(i)
|
||||
i1 := InvalidEdge{}
|
||||
buf, err := MarshalSchema(i1)
|
||||
require.Error(t, err)
|
||||
require.Nil(t, buf)
|
||||
|
||||
i2 := InvalidUUID{}
|
||||
buf, err = MarshalSchema(i2)
|
||||
require.Nil(t, buf)
|
||||
require.EqualError(t, err, `schema "InvalidUUID": expect type (func() uuid.UUID) for uuid default value`)
|
||||
}
|
||||
|
||||
type WithDefaults struct {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package field
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"math"
|
||||
"reflect"
|
||||
@@ -133,13 +134,18 @@ func Enum(name string) *enumBuilder {
|
||||
|
||||
// UUID returns a new Field with type UUID. An example for defining UUID field is as follows:
|
||||
//
|
||||
// field.UUID("id").
|
||||
// Default(uuid.New)
|
||||
// field.UUID("id", uuid.New())
|
||||
//
|
||||
func UUID(name string) *uuidBuilder {
|
||||
func UUID(name string, typ driver.Valuer) *uuidBuilder {
|
||||
rt := reflect.TypeOf(typ)
|
||||
return &uuidBuilder{&Descriptor{
|
||||
Name: name,
|
||||
Info: &TypeInfo{Type: TypeUUID, Nillable: true},
|
||||
Info: &TypeInfo{
|
||||
Type: TypeUUID,
|
||||
Nillable: true,
|
||||
Ident: rt.String(),
|
||||
PkgPath: rt.PkgPath(),
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -575,22 +581,15 @@ func (b *uuidBuilder) StructTag(s string) *uuidBuilder {
|
||||
return b
|
||||
}
|
||||
|
||||
// Type sets a custom type of the UUID field. It defaults to [16]byte.
|
||||
func (b *uuidBuilder) Type(typ interface{}) *uuidBuilder {
|
||||
t := reflect.TypeOf(typ)
|
||||
b.desc.Info.Ident = t.String()
|
||||
b.desc.Info.PkgPath = t.PkgPath()
|
||||
return b
|
||||
}
|
||||
|
||||
// Default sets the function that is applied to set default value
|
||||
// of the field on creation. For example:
|
||||
// of the field on creation. Codegen fails if the default function
|
||||
// doesn't return the same concrete that was set for the UUID type.
|
||||
//
|
||||
// field.UUID("id").
|
||||
// field.UUID("id", uuid.UUID{}).
|
||||
// Default(uuid.New)
|
||||
//
|
||||
func (b *uuidBuilder) Default(f func() [16]byte) *uuidBuilder {
|
||||
b.desc.Default = f
|
||||
func (b *uuidBuilder) Default(fn interface{}) *uuidBuilder {
|
||||
b.desc.Default = fn
|
||||
return b
|
||||
}
|
||||
|
||||
|
||||
@@ -155,18 +155,12 @@ func TestField_Enums(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestField_UUID(t *testing.T) {
|
||||
fd := field.UUID("id").
|
||||
Default(func() [16]byte { return uuid.New() }).
|
||||
Descriptor()
|
||||
assert.Equal(t, "id", fd.Name)
|
||||
assert.Equal(t, "[16]byte", fd.Info.String())
|
||||
assert.NotNil(t, fd.Default)
|
||||
|
||||
fd = field.UUID("id").
|
||||
Type(uuid.UUID{}).
|
||||
fd := field.UUID("id", uuid.UUID{}).
|
||||
Default(uuid.New).
|
||||
Descriptor()
|
||||
assert.Equal(t, "id", fd.Name)
|
||||
assert.Equal(t, "uuid.UUID", fd.Info.String())
|
||||
assert.Equal(t, "github.com/google/uuid", fd.Info.PkgPath)
|
||||
assert.Nil(t, fd.Default)
|
||||
assert.NotNil(t, fd.Default)
|
||||
assert.NotEmpty(t, fd.Default.(func() uuid.UUID)())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user