Skip to content
194 changes: 135 additions & 59 deletions mygorm/breedingbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,161 @@ package mygorm

import (
"github.com/jinzhu/gorm"
"time"
)

type TypeEnum struct {
slug string
}
type TypeEnum string

const (
TypeUnknown = TypeEnum("")
TypeString = TypeEnum("string")
TypeText = TypeEnum("text")
TypeCheckbox = TypeEnum("checkbox")
TypeInt = TypeEnum("integer")
TypeFloat = TypeEnum("floating point")
TypeDate = TypeEnum("date")
TypeDateTime = TypeEnum("timestamp")
TypeSelectOne = TypeEnum("select one")
TypeSelectMany = TypeEnum("select many") // []string
)

func (te TypeEnum) String() string {
return te.slug
var AllTypeEnums = []TypeEnum{
TypeUnknown,
TypeString,
TypeText,
TypeCheckbox,
TypeInt,
TypeFloat,
TypeDate,
TypeDateTime,
TypeSelectOne,
TypeSelectMany,
}

var (
TypeUnknown = TypeEnum{""}
TypeString = TypeEnum{"string"}
TypeText = TypeEnum{"text"}
TypeCheckbox = TypeEnum{"checkbox"}
TypeInt = TypeEnum{"integer"}
TypeFloat = TypeEnum{"floating point"}
TypeDate = TypeEnum{"date"}
TypeDateTime = TypeEnum{"timestamp"}
TypeSelectOne = TypeEnum{"select one"}
TypeSelectMany = TypeEnum{"select many"}
type QualityEnum string

const (
QualityNeutral = QualityEnum("neutral")
QualityBad = QualityEnum("bad")
QualityPerfect = QualityEnum("perfect")
)

var AllTypeEnums = []string{
TypeUnknown.slug,
TypeString.slug,
TypeText.slug,
TypeCheckbox.slug,
TypeInt.slug,
TypeFloat.slug,
TypeDate.slug,
TypeDateTime.slug,
TypeSelectOne.slug,
TypeSelectMany.slug,
var AllQualityEnums = []QualityEnum{
QualityNeutral,
QualityBad,
QualityPerfect,
}

func NewTypeEnum(s string) TypeEnum {
switch s {
case TypeString.slug:
return TypeString
case TypeText.slug:
return TypeText
case TypeCheckbox.slug:
return TypeCheckbox
case TypeInt.slug:
return TypeInt
case TypeFloat.slug:
return TypeFloat
case TypeDate.slug:
return TypeDate
case TypeDateTime.slug:
return TypeDateTime
case TypeSelectOne.slug:
return TypeSelectOne
case TypeSelectMany.slug:
return TypeSelectMany
}
return TypeUnknown
type DogTest struct {
gorm.Model
Name string `gorm:"unique; not null"`
SelectOne1 string `gorm:"not null"`
SelectOne2 string `gorm:"not null"`
SelectOne3 string `gorm:"not null"`
CheckBox1 bool `gorm:"not null"`
CheckBox2 bool `gorm:"not null"`
CheckBox3 bool `gorm:"not null"`
String1 string `gorm:"not null"`
String1Quality QualityEnum `gorm:"not null"`
Text1 string `gorm:"not null"`
Text1Quality QualityEnum `gorm:"not null"`
Integer1 int64 `gorm:"not null"`
Float1 float64 `gorm:"not null"`
Date1 time.Time `gorm:"not null"`
Timestamp1 time.Time `gorm:"not null"`
SelectMany1 []string `gorm:"not null"`
}

type BaseMetaFeature struct {
gorm.Model
Name string `gorm:"unique"`
ShortName string `gorm:"unique"`
Type TypeEnum
GroupID uint
Name string `gorm:"unique; not null"`
ShortName string `gorm:"unique; not null"`
Type TypeEnum `gorm:"not null"`
GroupID uint `gorm:"not null"`
Group FeatureGroup `gorm:"foreignkey:GroupID;association_autocreate:false;association_autoupdate:false"`
}

type FeatureGroup struct {
gorm.Model
Name string `gorm:"unique"`
ShortName string `gorm:"unique"`
ColorID uint
Color Color `gorm:"foreignkey:ColorID;association_autocreate:false;association_autoupdate:false"`
Name string `gorm:"unique; not null"`
ShortName string `gorm:"unique; not null"`
ColorID uint `gorm:"not null"`
Color Color `gorm:"foreignkey:ColorID;association_autocreate:false;association_autoupdate:false"`
}

type Color struct {
gorm.Model
Name string `gorm:"unique"`
HexValue string `gorm:"unique"`
Name string `gorm:"unique; not null"`
HexValue string `gorm:"unique; not null"`
}

type SelectOneMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
Order int `gorm:"not null"`
Value string `gorm:"not null"`
Quality QualityEnum `gorm:"not null"`
}

type CheckBoxMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
QualityChecked QualityEnum `gorm:"not null"`
QualityUnchecked QualityEnum `gorm:"not null"`
}

type StringMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
MinLength uint `gorm:"not null"`
MaxLength uint `gorm:"not null"`
}

type TextMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
MinLength uint `gorm:"not null"`
MaxLength uint `gorm:"not null"`
}

type IntegerMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
NeutralMin int64 `gorm:"not null"`
NeutralMax int64 `gorm:"not null"`
BadMin int64 `gorm:"not null"`
BadMax int64 `gorm:"not null"`
PerfectMin int64 `gorm:"not null"`
PerfectMax int64 `gorm:"not null"`
}

type FloatMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
NeutralMin float64 `gorm:"not null"`
NeutralMax float64 `gorm:"not null"`
BadMin float64 `gorm:"not null"`
BadMax float64 `gorm:"not null"`
PerfectMin float64 `gorm:"not null"`
PerfectMax float64 `gorm:"not null"`
}

type DateMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
// still decide
}

type TimestampMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
// still decide
}

type SelectManyMetaFeature struct {
BaseID uint `gorm:"not null"`
ColumnNum int `gorm:"not null"`
Order int `gorm:"not null"`
Value string `gorm:"not null"`
Quality QualityEnum `gorm:"not null"`
}
146 changes: 146 additions & 0 deletions mygorm/gorm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,16 @@ func TestDogsAndParents(t *testing.T) {
if err := db.Model(p1New).Association("Mother").Error; err != nil {
t.Fatalf("Mother association error: %v", err)
}

db.Model(p1New).Association("Mother").Find(&(p1New.Mother))
if p1New.Mother.ID != m.ID {
t.Errorf("p1New should have got '%s' as mother but instead it is '%s': %s", m.Name, p1New.Mother.Name, spew.Sdump(p1New))
}

if err := db.Model(p1New).Association("Father").Error; err != nil {
t.Fatalf("Father association error: %v", err)
}

db.Model(p1New).Association("Father").Find(&(p1New.Father))
if p1New.Father.ID != f.ID {
t.Errorf("p1New should have got '%s' as father but instead it is '%s': %s", f.Name, p1New.Father.Name, spew.Sdump(p1New))
Expand All @@ -83,13 +86,16 @@ func TestDogsAndParents(t *testing.T) {
if err := db.Model(p2New).Association("Mother").Error; err != nil {
t.Fatalf("Mother association error: %v", err)
}

db.Model(p2New).Association("Mother").Find(&(p2New.Mother))
if p2New.Mother.ID != m.ID {
t.Errorf("p2New should have got '%s' as mother but instead it is '%s': %s", m.Name, p2New.Mother.Name, spew.Sdump(p2New))
}

if err := db.Model(p2New).Association("Father").Error; err != nil {
t.Fatalf("Father association error: %v", err)
}

db.Model(p2New).Association("Father").Find(&(p2New.Father))
if p2New.Father.ID != f.ID {
t.Errorf("p2New should have got '%s' as father but instead it is '%s': %s", f.Name, p2New.Father.Name, spew.Sdump(p2New))
Expand Down Expand Up @@ -158,3 +164,143 @@ func TestColorAndFeatureGroups(t *testing.T) {
}

}

func TestBaseMetaFeatureAndFeatureGroups(t *testing.T) {
// create colors
c3 := &Color{Name: "blue", HexValue: "0000ff"}

// write to DB
if err := db.Create(c3).Error; err != nil {
t.Fatalf("Unable to create Color 3, %v", err)
}

// create feature groups
fg3 := &FeatureGroup{Name: "pigmente2", ColorID: c3.ID, ShortName: "pigments2"}
fg4 := &FeatureGroup{Name: "teeth", ColorID: c3.ID, ShortName: "teeth"}

// write to DB
if err := db.Create(fg3).Error; err != nil {
t.Fatalf("Unable to create feature group 1, %v", err)
}

// write to DB
if err := db.Create(fg4).Error; err != nil {
t.Fatalf("Unable to create feature group 2, %v", err)
}

// create BaseMetaFeature
f1 := &BaseMetaFeature{Name: "pigmente2", GroupID: fg3.ID, ShortName: "pigments2", Type: TypeText}
f2 := &BaseMetaFeature{Name: "pigmente3", GroupID: fg3.ID, ShortName: "pigments3", Type: TypeString}
f3 := &BaseMetaFeature{Name: "pigmente4", GroupID: fg3.ID, ShortName: "pigments4", Type: TypeCheckbox}
f4 := &BaseMetaFeature{Name: "teeth", GroupID: fg4.ID, ShortName: "teeth", Type: TypeDate}
f5 := &BaseMetaFeature{Name: "teeth2", GroupID: fg4.ID, ShortName: "teeth2", Type: TypeFloat}

// f1 ------------------------

// write to DB
if err := db.Create(f1).Error; err != nil {
t.Fatalf("Unable to create feature 1, %v", err)
}

// read from DB
f1New := &BaseMetaFeature{}
if err := db.First(f1New, f1.ID).Error; err != nil {
t.Fatalf("Unable to read the feature 1, %v", err)
}

if f1New.Type != TypeText {
t.Errorf("f1New should have got '%s' as type but instead it is '%s': %s", TypeText, f1New.Type, spew.Sdump(f1New))
}

// checking the association
if err := db.Model(f1New).Association("Group").Error; err != nil {
t.Fatalf("Group association error: %v", err)
}

// population association
db.Model(f1New).Association("Group").Find(&(f1New.Group))
if f1New.Group.ID != fg3.ID {
t.Errorf("f1New should have got '%s' as group but instead it is '%s': %s", fg3.Name, f1New.Group.Name, spew.Sdump(f1New))
}

// f2 ------------------------
// write to DB
if err := db.Create(f2).Error; err != nil {
t.Fatalf("Unable to create feature 2, %v", err)
}

// read from DB
f2New := &BaseMetaFeature{}
if err := db.First(f2New, f2.ID).Error; err != nil {
t.Fatalf("Unable to read the feature group 2, %v", err)
}

// checking the association
if err := db.Model(f2New).Association("Group").Error; err != nil {
t.Fatalf("Group association error: %v", err)
}

// population association
db.Model(f2New).Association("Group").Find(&(f2New.Group))
if f2New.Group.ID != fg3.ID {
t.Errorf("f2New should have got '%s' as group but instead it is '%s': %s", fg3.Name, f2New.Group.Name, spew.Sdump(f2New))
}

// f3 ------------------------
if err := db.Create(f3).Error; err != nil {
t.Fatalf("Unable to create feature group 3, %v", err)
}

f3New := &BaseMetaFeature{}
if err := db.First(f3New, f3.ID).Error; err != nil {
t.Fatalf("Unable to reade the feature group 3, %v", err)
}

if err := db.Model(f3New).Association("Group").Error; err != nil {
t.Fatalf("Group association error: %v", err)
}

db.Model(f3New).Association("Group").Find(&(f3New.Group))
if f3New.Group.ID != fg3.ID {
t.Errorf("f3new should have got '%s' as group but instead it is '%s': %s", fg3.Name, f3New.Group.Name, spew.Sdump(f3New))
}

// f4 ------------------------
if err := db.Create(f4).Error; err != nil {
t.Fatalf("Unable to create feature group 4, %v", err)
}

f4New := &BaseMetaFeature{}
if err := db.First(f4New, f4.ID).Error; err != nil {
t.Fatalf("Unable to reade the feature group 4, %v", err)
}

if err := db.Model(f4New).Association("Group").Error; err != nil {
t.Fatalf("Group association err: %v", err)
}

db.Model(f4New).Association("Group").Find(&(f4New.Group))
if f4New.Group.ID != fg4.ID {
t.Errorf("f4New should have got '%s' as group but instead it is '%s': %s", fg4.Name, f4New.Group.Name, spew.Sdump(f4New))
}

// f5 ------------------------
if err := db.Create(f5).Error; err != nil {
t.Fatalf("Unable to create feature group 5, %v", err)
}

f5New := &BaseMetaFeature{}
if err := db.First(f5New, f5.ID).Error; err != nil {
t.Fatalf("Unable to reade the feature group 5, %v", err)
}

if err := db.Model(f5New).Association("Group").Error; err != nil {
t.Fatalf("Group association err: %v", err)
}

db.Model(f5New).Association("Group").Find(&(f5New.Group))
if f5New.Group.ID != fg4.ID {
t.Errorf("f5New should have got '%s' as group but instead it is '%s': %s", fg4.Name,
f5New.Group.Name, spew.Sdump(f5New))
}
}
Binary file removed mygorm/test.db
Binary file not shown.