Refactor Model Struct

This commit is contained in:
Jinzhu 2015-02-18 12:30:09 +08:00
parent 9e5c64d611
commit 0d2c37e310
6 changed files with 80 additions and 60 deletions

View File

@ -156,8 +156,8 @@ func (association *Association) Count() int {
} else if relationship.Kind == "has_many" || relationship.Kind == "has_one" { } else if relationship.Kind == "has_many" || relationship.Kind == "has_one" {
whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName)) whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName))
countScope := scope.db.Model("").Table(newScope.QuotedTableName()).Where(whereSql, association.PrimaryKey) countScope := scope.db.Model("").Table(newScope.QuotedTableName()).Where(whereSql, association.PrimaryKey)
if relationship.ForeignType != "" { if relationship.PolymorphicType != "" {
countScope = countScope.Where(fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(ToDBName(relationship.ForeignType))), scope.TableName()) countScope = countScope.Where(fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.PolymorphicDBName)), scope.TableName())
} }
countScope.Count(&count) countScope.Count(&count)
} else if relationship.Kind == "belongs_to" { } else if relationship.Kind == "belongs_to" {

View File

@ -50,8 +50,8 @@ func TestHasOneAndHasManyAssociation(t *testing.T) {
t.Errorf("Comment 2 Should have post id") t.Errorf("Comment 2 Should have post id")
} }
comment3 := Comment{Content: "Comment 3", Post: Post{Title: "Title 3", Body: "Body 3"}} // comment3 := Comment{Content: "Comment 3", Post: Post{Title: "Title 3", Body: "Body 3"}}
DB.Save(&comment3) // DB.Save(&comment3)
} }
func TestRelated(t *testing.T) { func TestRelated(t *testing.T) {

View File

@ -46,8 +46,8 @@ func SaveAfterAssociations(scope *Scope) {
newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue()) newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue())
} }
if relationship.ForeignType != "" { if relationship.PolymorphicType != "" {
newScope.SetColumn(relationship.ForeignType, scope.TableName()) newScope.SetColumn(relationship.PolymorphicType, scope.TableName())
} }
scope.Err(newDB.Save(elem).Error) scope.Err(newDB.Save(elem).Error)
@ -80,8 +80,8 @@ func SaveAfterAssociations(scope *Scope) {
newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue()) newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue())
} }
if relationship.ForeignType != "" { if relationship.PolymorphicType != "" {
newScope.SetColumn(relationship.ForeignType, scope.TableName()) newScope.SetColumn(relationship.PolymorphicType, scope.TableName())
} }
scope.Err(scope.NewDB().Save(elem).Error) scope.Err(scope.NewDB().Save(elem).Error)
} }

View File

@ -14,6 +14,7 @@ import (
type ModelStruct struct { type ModelStruct struct {
PrimaryKeyField *StructField PrimaryKeyField *StructField
StructFields []*StructField StructFields []*StructField
ModelType reflect.Type
TableName string TableName string
} }
@ -53,7 +54,8 @@ func (structField *StructField) clone() *StructField {
type Relationship struct { type Relationship struct {
Kind string Kind string
ForeignType string PolymorphicType string
PolymorphicDBName string
ForeignFieldName string ForeignFieldName string
ForeignDBName string ForeignDBName string
AssociationForeignFieldName string AssociationForeignFieldName string
@ -134,6 +136,7 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
} }
} }
modelStruct.ModelType = scopeType
if scopeType.Kind() != reflect.Struct { if scopeType.Kind() != reflect.Struct {
return &modelStruct return &modelStruct
} }
@ -209,47 +212,63 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
if !field.IsNormal { if !field.IsNormal {
gormSettings := parseTagSetting(field.Tag.Get("gorm")) gormSettings := parseTagSetting(field.Tag.Get("gorm"))
many2many := gormSettings["MANY2MANY"] toModelStruct := scope.New(reflect.New(fieldStruct.Type).Interface()).GetModelStruct()
getForeignField := func(column string, fields []*StructField) *StructField {
for _, field := range fields {
if field.Name == column || field.DBName == ToDBName(column) {
return field
}
}
return nil
}
var relationship = &Relationship{}
foreignKey := gormSettings["FOREIGNKEY"] foreignKey := gormSettings["FOREIGNKEY"]
foreignType := gormSettings["FOREIGNTYPE"]
associationForeignKey := gormSettings["ASSOCIATIONFOREIGNKEY"]
if polymorphic := gormSettings["POLYMORPHIC"]; polymorphic != "" { if polymorphic := gormSettings["POLYMORPHIC"]; polymorphic != "" {
foreignKey = polymorphic + "Id" if polymorphicField := getForeignField(polymorphic+"Id", toModelStruct.StructFields); polymorphicField != nil {
foreignType = polymorphic + "Type" if polymorphicType := getForeignField(polymorphic+"Type", toModelStruct.StructFields); polymorphicType != nil {
relationship.ForeignFieldName = polymorphicField.Name
relationship.ForeignDBName = polymorphicField.DBName
relationship.PolymorphicType = polymorphicType.Name
relationship.PolymorphicDBName = polymorphicType.DBName
polymorphicType.IsForeignKey = true
polymorphicField.IsForeignKey = true
}
}
} }
switch indirectType.Kind() { switch indirectType.Kind() {
case reflect.Slice: case reflect.Slice:
typ := indirectType.Elem() if len(toModelStruct.StructFields) > 0 {
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
if typ.Kind() == reflect.Struct {
kind := "has_many"
if foreignKey == "" { if foreignKey == "" {
foreignKey = scopeType.Name() + "Id" foreignKey = scopeType.Name() + "Id"
} }
if many2many := gormSettings["MANY2MANY"]; many2many != "" {
relationship.Kind = "many_to_many"
relationship.JoinTable = many2many
associationForeignKey := gormSettings["ASSOCIATIONFOREIGNKEY"]
if associationForeignKey == "" { if associationForeignKey == "" {
associationForeignKey = typ.Name() + "Id" associationForeignKey = toModelStruct.ModelType.Name() + "Id"
} }
if many2many != "" { relationship.ForeignFieldName = foreignKey
kind = "many_to_many" relationship.ForeignDBName = ToDBName(foreignKey)
} else if !reflect.New(typ).Elem().FieldByName(foreignKey).IsValid() { relationship.AssociationForeignFieldName = associationForeignKey
foreignKey = "" relationship.AssociationForeignDBName = ToDBName(associationForeignKey)
field.Relationship = relationship
} else {
relationship.Kind = "has_many"
if foreignField := getForeignField(foreignKey, toModelStruct.StructFields); foreignField != nil {
relationship.ForeignFieldName = foreignField.Name
relationship.ForeignDBName = foreignField.DBName
foreignField.IsForeignKey = true
field.Relationship = relationship
} else if relationship.ForeignFieldName != "" {
field.Relationship = relationship
} }
field.Relationship = &Relationship{
JoinTable: many2many,
ForeignType: foreignType,
ForeignFieldName: foreignKey,
AssociationForeignFieldName: associationForeignKey,
ForeignDBName: ToDBName(foreignKey),
AssociationForeignDBName: ToDBName(associationForeignKey),
Kind: kind,
} }
} else { } else {
field.IsNormal = true field.IsNormal = true
@ -263,29 +282,30 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
} }
break break
} else { } else {
var belongsToForeignKey, hasOneForeignKey, kind string belongsToForeignKey := foreignKey
if belongsToForeignKey == "" {
if foreignKey == "" {
belongsToForeignKey = field.Name + "Id" belongsToForeignKey = field.Name + "Id"
hasOneForeignKey = scopeType.Name() + "Id"
} else {
belongsToForeignKey = foreignKey
hasOneForeignKey = foreignKey
} }
if _, ok := scopeType.FieldByName(belongsToForeignKey); ok { if foreignField := getForeignField(belongsToForeignKey, fields); foreignField != nil {
kind = "belongs_to" relationship.Kind = "belongs_to"
foreignKey = belongsToForeignKey relationship.ForeignFieldName = foreignField.Name
relationship.ForeignDBName = foreignField.DBName
foreignField.IsForeignKey = true
field.Relationship = relationship
} else { } else {
foreignKey = hasOneForeignKey if foreignKey == "" {
kind = "has_one" foreignKey = modelStruct.ModelType.Name() + "Id"
}
relationship.Kind = "has_one"
if foreignField := getForeignField(foreignKey, toModelStruct.StructFields); foreignField != nil {
relationship.ForeignFieldName = foreignField.Name
relationship.ForeignDBName = foreignField.DBName
foreignField.IsForeignKey = true
field.Relationship = relationship
} else if relationship.ForeignFieldName != "" {
field.Relationship = relationship
} }
field.Relationship = &Relationship{
ForeignFieldName: foreignKey,
ForeignDBName: ToDBName(foreignKey),
ForeignType: foreignType,
Kind: kind,
} }
} }
default: default:

View File

@ -410,8 +410,8 @@ func (scope *Scope) related(value interface{}, foreignKeys ...string) *Scope {
} else if relationship.Kind == "has_many" || relationship.Kind == "has_one" { } else if relationship.Kind == "has_many" || relationship.Kind == "has_one" {
sql := fmt.Sprintf("%v = ?", scope.Quote(relationship.ForeignDBName)) sql := fmt.Sprintf("%v = ?", scope.Quote(relationship.ForeignDBName))
query := toScope.db.Where(sql, scope.PrimaryKeyValue()) query := toScope.db.Where(sql, scope.PrimaryKeyValue())
if relationship.ForeignType != "" && toScope.HasColumn(relationship.ForeignType) { if relationship.PolymorphicType != "" {
query = query.Where(fmt.Sprintf("%v = ?", scope.Quote(ToDBName(relationship.ForeignType))), scope.TableName()) query = query.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.PolymorphicDBName)), scope.TableName())
} }
scope.Err(query.Find(value).Error) scope.Err(query.Find(value).Error)
} }

View File

@ -160,7 +160,7 @@ type Comment struct {
Id int64 Id int64
PostId int64 PostId int64
Content string Content string
Post Post // Post Post
} }
// Scanner // Scanner