Skip to content
Snippets Groups Projects
Commit cfde23af authored by Alena Petraki's avatar Alena Petraki :nail_care_tone1: Committed by Pavel Antonov
Browse files

Добавлен метод для определения, является ли поле SingleLocale

parent ec7ae7d4
Branches
Tags
No related merge requests found
Showing
with 375 additions and 73 deletions
...@@ -47,6 +47,8 @@ func TestEqualSchema(t *testing.T) { ...@@ -47,6 +47,8 @@ func TestEqualSchema(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
s2 := schema.New() s2 := schema.New()
err = json.Unmarshal(b, s2) err = json.Unmarshal(b, s2)
s1.ClearState()
s2.ClearState()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, s1.Field, s2.Field) require.Equal(t, s1.Field, s2.Field)
} }
......
...@@ -22,6 +22,27 @@ type FileParameters struct { ...@@ -22,6 +22,27 @@ type FileParameters struct {
func (p FileParameters) Type() field.Type { return p.t } func (p FileParameters) Type() field.Type { return p.t }
func (p *FileParameters) Clone(reset bool) field.Parameters { return p } func (p *FileParameters) Clone(reset bool) field.Parameters { return p }
func (p FileParameters) GetField(f *field.Field, name string) *field.Field {
var fld *field.Field
switch name {
case "id", "name", "mimeType", "url", "key":
fld = field.String()
case "size":
fld = field.Number(field.NumberFormatInt)
}
return f.SetFieldState(name, fld)
}
func (p FileParameters) ListFields(f *field.Field, filter ...field.FieldFilterFunc) []*field.Field {
return []*field.Field{
f.SetFieldState("id", field.String()),
f.SetFieldState("name", field.String()),
f.SetFieldState("mimeType", field.String()),
f.SetFieldState("size", field.Number(field.NumberFormatInt)),
f.SetFieldState("url", field.String()),
f.SetFieldState("key", field.String()),
}
}
type FileType struct { type FileType struct {
fs Files fs Files
...@@ -145,17 +166,6 @@ func (t *FileType) IsEmpty(v interface{}) bool { ...@@ -145,17 +166,6 @@ func (t *FileType) IsEmpty(v interface{}) bool {
return !ok || f.ID == "" return !ok || f.ID == ""
} }
func (p FileParameters) GetField(path string) (fld *field.Field) {
switch path {
case "id", "name", "mimeType", "url", "key":
return field.String()
case "size":
return field.Number(field.NumberFormatInt)
default:
return nil
}
}
func init() { func init() {
// По умолчанию без FS // По умолчанию без FS
// Если нужны подписанные URL, и загрузка на FS, нужно зарегистрировать корректный типа // Если нужны подписанные URL, и загрузка на FS, нужно зарегистрировать корректный типа
......
...@@ -72,6 +72,7 @@ func TestGetField(t *testing.T) { ...@@ -72,6 +72,7 @@ func TestGetField(t *testing.T) {
), ),
"arr", field.Array(field.Object("a", field.Time())), "arr", field.Array(field.Object("a", field.Time())),
) )
sch.ClearState()
tests := []struct { tests := []struct {
name string name string
......
...@@ -18,7 +18,6 @@ type ReferenceParameters struct { ...@@ -18,7 +18,6 @@ type ReferenceParameters struct {
} }
func (p ReferenceParameters) Type() field.Type { return &ReferenceType{} } func (p ReferenceParameters) Type() field.Type { return &ReferenceType{} }
func (p ReferenceParameters) Clone(reset bool) field.Parameters { func (p ReferenceParameters) Clone(reset bool) field.Parameters {
if p.AllowedCollections != nil { if p.AllowedCollections != nil {
cols := make([]string, 0, len(p.AllowedCollections)) cols := make([]string, 0, len(p.AllowedCollections))
...@@ -27,6 +26,10 @@ func (p ReferenceParameters) Clone(reset bool) field.Parameters { ...@@ -27,6 +26,10 @@ func (p ReferenceParameters) Clone(reset bool) field.Parameters {
} }
return &p return &p
} }
func (p ReferenceParameters) GetField(f *field.Field, name string) *field.Field { return nil }
func (p ReferenceParameters) ListFields(f *field.Field, filter ...field.FieldFilterFunc) []*field.Field {
return nil
}
type ReferenceType struct{} type ReferenceType struct{}
......
...@@ -22,6 +22,22 @@ func (p ArrayParameters) Clone(reset bool) Parameters { ...@@ -22,6 +22,22 @@ func (p ArrayParameters) Clone(reset bool) Parameters {
return &ArrayParameters{Item: p.Item.Clone(reset)} return &ArrayParameters{Item: p.Item.Clone(reset)}
} }
func (a ArrayParameters) GetField(f *Field, name string) *Field {
f.SetFieldState("Item", a.Item)
if name == "" || name == "Item" {
return a.Item
}
return a.Item.GetField(name)
}
func (a ArrayParameters) ListFields(f *Field, filterFunc ...FieldFilterFunc) []*Field {
f.SetFieldState("Item", a.Item)
return []*Field{a.Item}
}
type ArrayType struct{} type ArrayType struct{}
func (ArrayType) Name() string { func (ArrayType) Name() string {
......
...@@ -12,6 +12,8 @@ type BoolParameters struct{} ...@@ -12,6 +12,8 @@ type BoolParameters struct{}
func (b BoolParameters) Type() Type { return boolType } func (b BoolParameters) Type() Type { return boolType }
func (b *BoolParameters) Clone(reset bool) Parameters { return b } func (b *BoolParameters) Clone(reset bool) Parameters { return b }
func (b BoolParameters) GetField(f *Field, name string) *Field { return nil }
func (b BoolParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
type BoolType struct{} type BoolType struct{}
......
...@@ -49,6 +49,17 @@ type Include struct { ...@@ -49,6 +49,17 @@ type Include struct {
Optional bool `json:"optional,omitempty"` Optional bool `json:"optional,omitempty"`
} }
// State - состояние поля времени выполнения
type State struct {
Name string
DataPath string
SchemaPath string
SingleLocale bool
Parent *Field
Inlined bool
HasInline bool
}
type Field struct { type Field struct {
Title string `json:"title,omitempty"` // Название поля (Например: name) Title string `json:"title,omitempty"` // Название поля (Например: name)
Description string `json:"description,omitempty"` // Описание поле (Например: User name) Description string `json:"description,omitempty"` // Описание поле (Например: User name)
...@@ -63,6 +74,7 @@ type Field struct { ...@@ -63,6 +74,7 @@ type Field struct {
Options Options `json:"options,omitempty"` // Дополнительные опции Options Options `json:"options,omitempty"` // Дополнительные опции
Condition string `json:"condition,omitempty"` // Условие отображения поля Condition string `json:"condition,omitempty"` // Условие отображения поля
AdditionalValues bool `json:"additional_values,omitempty"` // Разрешает дополнительные значения вне ограничений правил AdditionalValues bool `json:"additional_values,omitempty"` // Разрешает дополнительные значения вне ограничений правил
State *State `json:"-"` // Состояние поля времени выполнения
} }
// TODO: Replace with Named field??? // TODO: Replace with Named field???
...@@ -84,6 +96,32 @@ func NewField(params Parameters, opts ...interface{}) *Field { ...@@ -84,6 +96,32 @@ func NewField(params Parameters, opts ...interface{}) *Field {
return f return f
} }
// GetState возвращает состояние поля времени выполнения
func (f Field) GetState() *State {
return f.State
}
// ClearState очищает состояние поля и всех вложенных полей
//
// Схемы нельзя сравнивать с активным состоянием с помощью `reflect.DeepEqual` или `assert.Equal`.
// Предварительно нужно сделать `ClearState`.
// После очистки состояния полей не будут рассчитываться. Для повторного включения состояния используйте `EnableState`
func (f *Field) ClearState() *Field {
f.State = nil
for _, fld := range f.ListFields() {
fld.ClearState()
}
return f
}
// EnableState включает расчет состояния поля и всех вложенных полей
//
// Без включения состояния поля, невозможно получить доступ к данным времени выполнения
// schema.New включает состояние для схемы при создании
func (f *Field) EnableState() {
f.State = &State{}
}
func (f Field) GetType() Type { func (f Field) GetType() Type {
return f.Params.Type() return f.Params.Type()
} }
...@@ -164,6 +202,10 @@ func (f Field) SetSingleLocale(r bool) *Field { ...@@ -164,6 +202,10 @@ func (f Field) SetSingleLocale(r bool) *Field {
return &f return &f
} }
func (f Field) IsSingleLocale() bool {
return f.SingleLocale || (f.State != nil && f.State.SingleLocale)
}
func (f Field) SetIndexed(r bool) *Field { func (f Field) SetIndexed(r bool) *Field {
f.Indexed = r f.Indexed = r
return &f return &f
...@@ -257,46 +299,91 @@ func (f *Field) Prepare() error { ...@@ -257,46 +299,91 @@ func (f *Field) Prepare() error {
return nil return nil
} }
// GetField возвращает поле по строковому пути func (f *Field) SetFieldState(name string, fld *Field) *Field {
func (f *Field) GetField(path string) *Field { if f != nil && fld != nil && f.State != nil && fld.State == nil {
if path == "" { fld.State = f.getFieldState(name, fld)
switch params := f.Params.(type) { }
case *ArrayParameters: return fld
// Возвращаем поле Item если путь указан как "arr."
return params.Item
} }
// GetFieldState возвращает состояние вложенного поля
func (f *Field) getFieldState(name string, fld *Field) *State {
if f.State == nil {
return nil return nil
} }
state := State{
SchemaPath: name,
DataPath: name,
Name: name,
}
dataPath := f.State.DataPath
switch params := f.Params.(type) { switch params := f.Params.(type) {
case *ObjectParameters: case *ObjectParameters:
pp := strings.SplitN(path, FieldSeparator, 2) if params.Inline {
last := strings.LastIndex(dataPath, ".")
if last > 0 {
dataPath = dataPath[:last]
} else {
dataPath = ""
}
state.Inlined = true
}
if dataPath != "" {
state.DataPath = dataPath + FieldSeparator + state.DataPath
}
for k, v := range params.Fields { case *ArrayParameters:
state.DataPath = dataPath // Remove item from path
}
p, ok := v.Params.(*ObjectParameters) state.SingleLocale = f.IsSingleLocale() || fld.SingleLocale
if ok && p.Inline {
f := v.GetField(path) if f.State.SchemaPath != "" {
if f != nil { state.SchemaPath = f.State.SchemaPath + FieldSeparator + state.SchemaPath
return f
} }
state.Parent = f
state.HasInline = f.State.HasInline || state.Inlined
return &state
} }
if k == pp[0] { func (f *Field) GetFieldByName(name string) *Field {
if len(pp) == 1 { return f.Params.GetField(f, name)
return v }
// GetField возвращает поле по строковому пути
func (f *Field) GetField(path string) *Field {
name := ""
parts := strings.SplitN(path, FieldSeparator, 2)
if len(parts) > 0 {
name = parts[0]
} }
return v.GetField(pp[1])
fld := f.GetFieldByName(name)
if fld != nil && len(parts) > 1 {
return fld.GetField(parts[1])
} }
return fld
} }
case Fielder:
return params.GetField(path)
case *ArrayParameters: // ListFields возвращает массив вложенных полей данного поля
return params.Item.GetField(path) func (f *Field) ListFields(filter ...FieldFilterFunc) []*Field {
fields := f.Params.ListFields(f, filter...)
return fields
} }
return nil // ListFieldsRecursive возвращает массив всех вложенных полей рекурсивно
func (f *Field) ListFieldsRecursive(filter ...FieldFilterFunc) []*Field {
fields := f.ListFields(filter...)
for _, fld := range fields {
fields = append(fields, fld.ListFieldsRecursive(filter...)...)
}
return fields
} }
// GetFieldsPath возвращает полный путь для массива полей // GetFieldsPath возвращает полный путь для массива полей
...@@ -311,6 +398,8 @@ type FilterFunc func(*Field, string) bool ...@@ -311,6 +398,8 @@ type FilterFunc func(*Field, string) bool
func GetAll(field *Field, path string) bool { return true } func GetAll(field *Field, path string) bool { return true }
// GetFields возвращает массив полей с путем???
// DEPRECATED: использовать ListFields или ListFieldsRecursive
func (f *Field) GetFields(filterFunc FilterFunc, pathPrefix ...string) (res []PathField) { func (f *Field) GetFields(filterFunc FilterFunc, pathPrefix ...string) (res []PathField) {
var path string var path string
...@@ -382,22 +471,26 @@ func getFieldsObject(path string, params *ObjectParameters, filterFunc FilterFun ...@@ -382,22 +471,26 @@ func getFieldsObject(path string, params *ObjectParameters, filterFunc FilterFun
return res return res
} }
// GetNestedFields возвращает вложенные поля
// DEPRECATED: использовать ListFields
func (f *Field) GetNestedFields() []*Field { func (f *Field) GetNestedFields() []*Field {
switch params := f.Params.(type) { return f.ListFields()
case *ObjectParameters:
flds := make([]*Field, 0, len(params.Fields)) //switch params := f.Params.(type) {
for _, v := range params.Fields { //case *ObjectParameters:
if v == nil { // flds := make([]*Field, 0, len(params.Fields))
continue // for _, v := range params.Fields {
} // if v == nil {
flds = append(flds, v) // continue
} // }
return flds // flds = append(flds, v)
case *ArrayParameters: // }
return []*Field{params.Item} // return flds
} //case *ArrayParameters:
// return []*Field{params.Item}
return nil //}
//
//return nil
} }
// Clone создает копию поля // Clone создает копию поля
......
...@@ -61,6 +61,8 @@ func (f *Field) UnmarshalJSON(b []byte) error { ...@@ -61,6 +61,8 @@ func (f *Field) UnmarshalJSON(b []byte) error {
} }
} }
j.FieldData.State = f.State
*f = Field(j.FieldData) *f = Field(j.FieldData)
f.Params = params f.Params = params
_ = f.Prepare() _ = f.Prepare()
......
package field
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestField_GetField(t *testing.T) {
sch := Object(
"f1", Object(
"a", String(),
"b", String().SetSingleLocale(true),
),
"f3", Object( // inline object
true,
"a", String(),
"b", Object(true, "c", String()),
).SetSingleLocale(true),
"f4", Array(Object("a", String())),
"f5", Array(String()),
"f6", Object(true, "f6", Object("a", String())),
)
sch.EnableState()
tests := []struct {
name string
path string
want *State
}{
{"Object", "f1", &State{Name: "f1", DataPath: "f1", SchemaPath: "f1", Parent: sch}},
{"Object field", "f1.a", &State{Name: "a", DataPath: "f1.a", SchemaPath: "f1.a", Parent: sch.GetField("f1")}},
{"Field with SingleLocale", "f1.b", &State{Name: "b", DataPath: "f1.b", SchemaPath: "f1.b", Parent: sch.GetField("f1"), SingleLocale: true}},
{"Object with SingleLocale", "f3", &State{Name: "f3", DataPath: "f3", SchemaPath: "f3", Parent: sch, SingleLocale: true}},
{"Inline", "a", &State{Name: "a", DataPath: "a", SchemaPath: "f3.a", Parent: sch.GetField("f3"), SingleLocale: true, Inlined: true, HasInline: true}},
{"Inline of inline", "c", &State{Name: "c", DataPath: "c", SchemaPath: "f3.b.c", Parent: sch.GetField("f3.b"), SingleLocale: true, Inlined: true, HasInline: true}},
{"Inline of inline (direct)", "f3.b.c", &State{Name: "c", DataPath: "c", SchemaPath: "f3.b.c", Parent: sch.GetField("f3.b"), SingleLocale: true, Inlined: true, HasInline: true}},
{"Array of Objects", "f4", &State{Name: "f4", DataPath: "f4", SchemaPath: "f4", Parent: sch}},
{"Array of Objects (Item)", "f4.Item", &State{Name: "Item", DataPath: "f4", SchemaPath: "f4.Item", Parent: sch.GetField("f4")}},
{"Array of Objects (Item field)", "f4.Item.a", &State{Name: "a", DataPath: "f4.a", SchemaPath: "f4.Item.a", Parent: sch.GetField("f4.Item")}},
{"Array of Objects (Item field direct)", "f4.a", &State{Name: "a", DataPath: "f4.a", SchemaPath: "f4.Item.a", Parent: sch.GetField("f4.Item")}},
{"Array of Strings", "f5", &State{Name: "f5", DataPath: "f5", SchemaPath: "f5", Parent: sch}},
{"Array of Strings (Item)", "f5.Item", &State{Name: "Item", DataPath: "f5", SchemaPath: "f5.Item", Parent: sch.GetField("f5")}},
{"Inline Same name not found", "f6.a", nil},
{"Inline Same name (direct)", "f6.f6.a", &State{Name: "a", DataPath: "f6.a", SchemaPath: "f6.f6.a", Parent: sch.GetField("f6.f6"), HasInline: true}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := sch.GetField(tt.path)
var st *State
if got != nil {
st = got.State
}
assert.Equal(t, tt.want, st)
sch.ClearState()
sch.EnableState()
if got != nil {
assert.Nil(t, got.State)
}
})
}
}
func TestField_ListFieldsRecursive(t *testing.T) {
sch := Object(
"f1", Object(
"f1a", String(),
"f1b", String().SetSingleLocale(true),
),
"f2", String(),
"f3", Object( // inline object
true,
"f3a", String(),
"f3b", Object(true, "f3bc", String()),
).SetSingleLocale(true),
"f4", Array(Object("f4a", String())),
"f5", Array(String()),
"f6", Object(true, "f6", Object("f6a", String())),
)
sch.EnableState()
fields := sch.ListFieldsRecursive()
assert.Len(t, fields, 16)
for _, f := range fields {
assert.NotNil(t, f.State)
assert.NotEmpty(t, f.State.Name)
}
}
func TestField_CloneWithState(t *testing.T) {
f := Object("a", String())
fld := f.Clone(false)
assert.Nil(t, fld.State)
f.EnableState()
fld = f.Clone(false)
assert.NotNil(t, fld.State)
}
...@@ -16,6 +16,8 @@ type LocationParameters struct{} ...@@ -16,6 +16,8 @@ type LocationParameters struct{}
func (p LocationParameters) Type() Type { return locationType } func (p LocationParameters) Type() Type { return locationType }
func (p LocationParameters) Clone(reset bool) Parameters { return &LocationParameters{} } func (p LocationParameters) Clone(reset bool) Parameters { return &LocationParameters{} }
func (p LocationParameters) GetField(f *Field, name string) *Field { return nil }
func (p LocationParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
func (p LocationParameters) GetMongoIndexes(path string, f *Field) []mongo.IndexModel { func (p LocationParameters) GetMongoIndexes(path string, f *Field) []mongo.IndexModel {
var add, geo mongo.IndexModel var add, geo mongo.IndexModel
......
...@@ -24,6 +24,8 @@ type NumberParameters struct { ...@@ -24,6 +24,8 @@ type NumberParameters struct {
func (NumberParameters) Type() Type { return numberType } func (NumberParameters) Type() Type { return numberType }
func (p NumberParameters) Clone(reset bool) Parameters { return &p } func (p NumberParameters) Clone(reset bool) Parameters { return &p }
func (p NumberParameters) GetField(f *Field, name string) *Field { return nil }
func (p NumberParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
type NumberType struct{} type NumberType struct{}
......
...@@ -36,6 +36,39 @@ func (p ObjectParameters) Clone(reset bool) Parameters { ...@@ -36,6 +36,39 @@ func (p ObjectParameters) Clone(reset bool) Parameters {
return &p return &p
} }
func (p ObjectParameters) GetField(f *Field, name string) *Field {
// Поиск поля в текущем объекте
if fld, ok := p.Fields[name]; ok {
return f.SetFieldState(name, fld)
}
// Поиск поля во вложенных Inline объектах
for k, v := range p.Fields {
if p, ok := v.Params.(*ObjectParameters); ok {
if p.Inline {
v = f.SetFieldState(k, v)
if fld := v.GetFieldByName(name); fld != nil {
return fld
}
}
}
}
return nil
}
func (p ObjectParameters) ListFields(f *Field, filterFunc ...FieldFilterFunc) []*Field {
var fields []*Field
for k, fld := range p.Fields {
f.SetFieldState(k, fld)
if !ApplyFilterFunc(filterFunc, fld) {
continue
}
fields = append(fields, fld)
}
return fields
}
// IsInlineObject определяет являться ли поле name инлайн объектом // IsInlineObject определяет являться ли поле name инлайн объектом
func (p ObjectParameters) IsInlineObject(name string) bool { func (p ObjectParameters) IsInlineObject(name string) bool {
fld, ok := p.Fields[name] fld, ok := p.Fields[name]
......
...@@ -14,6 +14,8 @@ type PrimaryKeyParameters struct{} ...@@ -14,6 +14,8 @@ type PrimaryKeyParameters struct{}
func (p PrimaryKeyParameters) Type() Type { return primaryKeyType } func (p PrimaryKeyParameters) Type() Type { return primaryKeyType }
func (p *PrimaryKeyParameters) Clone(reset bool) Parameters { return p } func (p *PrimaryKeyParameters) Clone(reset bool) Parameters { return p }
func (p PrimaryKeyParameters) GetField(f *Field, name string) *Field { return nil }
func (p PrimaryKeyParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
type PrimaryKeyType struct{} type PrimaryKeyType struct{}
......
...@@ -12,6 +12,8 @@ type StringParameters struct{} ...@@ -12,6 +12,8 @@ type StringParameters struct{}
func (s StringParameters) Type() Type { return stringType } func (s StringParameters) Type() Type { return stringType }
func (s *StringParameters) Clone(reset bool) Parameters { return s } func (s *StringParameters) Clone(reset bool) Parameters { return s }
func (s StringParameters) GetField(f *Field, name string) *Field { return nil }
func (s StringParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
type StringType struct{} type StringType struct{}
......
...@@ -19,6 +19,8 @@ type TimeParameters struct { ...@@ -19,6 +19,8 @@ type TimeParameters struct {
func (p TimeParameters) Type() Type { return timeType } func (p TimeParameters) Type() Type { return timeType }
func (p TimeParameters) Clone(reset bool) Parameters { return &p } func (p TimeParameters) Clone(reset bool) Parameters { return &p }
func (p TimeParameters) GetField(f *Field, name string) *Field { return nil }
func (p TimeParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
func (p TimeParameters) GetLayout() string { func (p TimeParameters) GetLayout() string {
if p.Layout != "" { if p.Layout != "" {
......
...@@ -15,6 +15,8 @@ type TimestampParameters struct{} ...@@ -15,6 +15,8 @@ type TimestampParameters struct{}
func (t TimestampParameters) Type() Type { return timestampType } func (t TimestampParameters) Type() Type { return timestampType }
func (t *TimestampParameters) Clone(reset bool) Parameters { return t } func (t *TimestampParameters) Clone(reset bool) Parameters { return t }
func (t TimestampParameters) GetField(f *Field, name string) *Field { return nil }
func (t TimestampParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
type TimestampType struct{} type TimestampType struct{}
......
...@@ -10,10 +10,23 @@ var ( ...@@ -10,10 +10,23 @@ var (
registry sync.Map registry sync.Map
) )
type FieldFilterFunc func(f *Field) bool
func ApplyFilterFunc(filterFunc []FieldFilterFunc, fld *Field) bool {
for _, f := range filterFunc {
if !f(fld) {
return false
}
}
return true
}
// Parameters - интерфейс который должен реализовывать параметр конкретного типа // Parameters - интерфейс который должен реализовывать параметр конкретного типа
type Parameters interface { type Parameters interface {
Type() Type Type() Type
Clone(reset bool) Parameters Clone(reset bool) Parameters
GetField(f *Field, name string) *Field
ListFields(f *Field, filter ...FieldFilterFunc) []*Field
} }
// Type - тип поля, отвечает за получение, кодирование и декодирование параметров для данного типа // Type - тип поля, отвечает за получение, кодирование и декодирование параметров для данного типа
......
...@@ -16,6 +16,8 @@ type UnknownParameters struct { ...@@ -16,6 +16,8 @@ type UnknownParameters struct {
func (UnknownParameters) Type() Type { return unknownType } func (UnknownParameters) Type() Type { return unknownType }
func (p UnknownParameters) Clone(reset bool) Parameters { return &p } func (p UnknownParameters) Clone(reset bool) Parameters { return &p }
func (p UnknownParameters) GetField(f *Field, name string) *Field { return nil }
func (p UnknownParameters) ListFields(f *Field, filter ...FieldFilterFunc) []*Field { return nil }
type UnknownType struct{} type UnknownType struct{}
......
...@@ -19,7 +19,9 @@ type Schema struct { ...@@ -19,7 +19,9 @@ type Schema struct {
} }
func New(kv ...interface{}) *Schema { func New(kv ...interface{}) *Schema {
return &Schema{Field: *field.Object(kv...)} s := &Schema{Field: *field.Object(kv...)}
s.Field.EnableState()
return s
} }
func NewFromField(f *field.Field) *Schema { func NewFromField(f *field.Field) *Schema {
...@@ -46,6 +48,11 @@ func (s *Schema) Clone(reset bool) *Schema { ...@@ -46,6 +48,11 @@ func (s *Schema) Clone(reset bool) *Schema {
} }
} }
func (s *Schema) ClearState() *Schema {
s.Field.ClearState()
return s
}
func (s *Schema) Equal(sch *Schema) bool { func (s *Schema) Equal(sch *Schema) bool {
if s == sch { if s == sch {
return true return true
...@@ -86,7 +93,10 @@ func (s *Schema) ConvertTypes() error { ...@@ -86,7 +93,10 @@ func (s *Schema) ConvertTypes() error {
if err != nil { if err != nil {
return errors.Wrap(err, "marshal schema") return errors.Wrap(err, "marshal schema")
} }
// сохраняем состояние cхемы
state := s.Field.State
*s = *New() *s = *New()
s.Field.State = state
return errors.Wrap(s.UnmarshalJSON(b), "unmarshal schema") return errors.Wrap(s.UnmarshalJSON(b), "unmarshal schema")
} }
......
...@@ -70,6 +70,8 @@ func TestSchema_UnmarshalJSON(t *testing.T) { ...@@ -70,6 +70,8 @@ func TestSchema_UnmarshalJSON(t *testing.T) {
if err := schema.UnmarshalJSON(tt.b); (err != nil) != tt.wantErr { if err := schema.UnmarshalJSON(tt.b); (err != nil) != tt.wantErr {
t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
} }
schema.ClearState()
tt.want.ClearState()
assert.Equal(t, tt.want, schema) assert.Equal(t, tt.want, schema)
}) })
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment