Modify struct when update association

This commit is contained in:
Jinzhu 2015-02-24 18:48:48 +08:00
parent 0f08058713
commit eb480cc085
2 changed files with 38 additions and 9 deletions

View File

@ -78,8 +78,25 @@ func (association *Association) Delete(values ...interface{}) *Association {
relationship.JoinTable, association.Scope.Quote(relationship.ForeignDBName), relationship.JoinTable, association.Scope.Quote(relationship.ForeignDBName),
relationship.JoinTable, association.Scope.Quote(relationship.AssociationForeignDBName)) relationship.JoinTable, association.Scope.Quote(relationship.AssociationForeignDBName))
association.Scope.db.Model("").Table(relationship.JoinTable). if err := association.Scope.db.Model("").Table(relationship.JoinTable).
Where(whereSql, association.PrimaryKey, primaryKeys).Delete("") Where(whereSql, association.PrimaryKey, primaryKeys).Delete("").Error; err == nil {
leftValues := reflect.Zero(association.Field.Field.Type())
for i := 0; i < association.Field.Field.Len(); i++ {
value := association.Field.Field.Index(i)
if primaryField := association.Scope.New(value.Interface()).PrimaryKeyField(); primaryField != nil {
var included = false
for _, primaryKey := range primaryKeys {
if equalAsString(primaryKey, primaryField.Field.Interface()) {
included = true
}
}
if !included {
leftValues = reflect.Append(leftValues, value)
}
}
}
association.Field.Set(leftValues)
}
} else { } else {
association.setErr(errors.New("delete only support many to many")) association.setErr(errors.New("delete only support many to many"))
} }
@ -94,6 +111,7 @@ func (association *Association) Replace(values ...interface{}) *Association {
field := association.Field.Field field := association.Field.Field
oldPrimaryKeys := association.getPrimaryKeys(field.Interface()) oldPrimaryKeys := association.getPrimaryKeys(field.Interface())
association.Field.Set(reflect.Zero(association.Field.Field.Type()))
association.Append(values...) association.Append(values...)
newPrimaryKeys := association.getPrimaryKeys(field.Interface()) newPrimaryKeys := association.getPrimaryKeys(field.Interface())
@ -130,7 +148,11 @@ func (association *Association) Clear() *Association {
scope := association.Scope scope := association.Scope
if relationship.Kind == "many_to_many" { if relationship.Kind == "many_to_many" {
whereSql := fmt.Sprintf("%v.%v = ?", relationship.JoinTable, scope.Quote(relationship.ForeignDBName)) whereSql := fmt.Sprintf("%v.%v = ?", relationship.JoinTable, scope.Quote(relationship.ForeignDBName))
scope.db.Model("").Table(relationship.JoinTable).Where(whereSql, association.PrimaryKey).Delete("") if err := scope.db.Model("").Table(relationship.JoinTable).Where(whereSql, association.PrimaryKey).Delete("").Error; err == nil {
association.Field.Set(reflect.Zero(association.Field.Field.Type()))
} else {
association.setErr(err)
}
} else { } else {
association.setErr(errors.New("clear only support many to many")) association.setErr(errors.New("clear only support many to many"))
} }

View File

@ -1,6 +1,9 @@
package gorm_test package gorm_test
import "testing" import (
"os"
"testing"
)
func TestHasOneAndHasManyAssociation(t *testing.T) { func TestHasOneAndHasManyAssociation(t *testing.T) {
DB.DropTable(Category{}) DB.DropTable(Category{})
@ -172,11 +175,15 @@ func TestManyToMany(t *testing.T) {
} }
// Delete // Delete
user.Languages = []Language{}
DB.Model(&user).Association("Languages").Find(&user.Languages)
var language Language var language Language
DB.Where("name = ?", "EE").First(&language) DB.Where("name = ?", "EE").First(&language)
DB.Model(&user).Association("Languages").Delete(language, &language) DB.Model(&user).Association("Languages").Delete(language, &language)
if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-1 { if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-1 || len(user.Languages) != len(totalLanguages)-1 {
t.Errorf("Relations should be deleted with Delete") t.Errorf("Relations should be deleted with Delete")
os.Exit(1)
} }
if DB.Where("name = ?", "EE").First(&Language{}).RecordNotFound() { if DB.Where("name = ?", "EE").First(&Language{}).RecordNotFound() {
t.Errorf("Language EE should not be deleted") t.Errorf("Language EE should not be deleted")
@ -189,7 +196,7 @@ func TestManyToMany(t *testing.T) {
DB.Save(&user2) DB.Save(&user2)
DB.Model(&user).Association("Languages").Delete(languages, &languages) DB.Model(&user).Association("Languages").Delete(languages, &languages)
if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-3 { if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-3 || len(user.Languages) != len(totalLanguages)-3 {
t.Errorf("Relations should be deleted with Delete") t.Errorf("Relations should be deleted with Delete")
} }
@ -201,18 +208,18 @@ func TestManyToMany(t *testing.T) {
var languageB Language var languageB Language
DB.Where("name = ?", "BB").First(&languageB) DB.Where("name = ?", "BB").First(&languageB)
DB.Model(&user).Association("Languages").Replace(languageB) DB.Model(&user).Association("Languages").Replace(languageB)
if DB.Model(&user).Association("Languages").Count() != 1 { if len(user.Languages) != 1 || DB.Model(&user).Association("Languages").Count() != 1 {
t.Errorf("Relations should be replaced") t.Errorf("Relations should be replaced")
} }
DB.Model(&user).Association("Languages").Replace(&[]Language{{Name: "FF"}, {Name: "JJ"}}) DB.Model(&user).Association("Languages").Replace(&[]Language{{Name: "FF"}, {Name: "JJ"}})
if DB.Model(&user).Association("Languages").Count() != len([]string{"FF", "JJ"}) { if len(user.Languages) != 2 || DB.Model(&user).Association("Languages").Count() != len([]string{"FF", "JJ"}) {
t.Errorf("Relations should be replaced") t.Errorf("Relations should be replaced")
} }
// Clear // Clear
DB.Model(&user).Association("Languages").Clear() DB.Model(&user).Association("Languages").Clear()
if DB.Model(&user).Association("Languages").Count() != 0 { if len(user.Languages) != 0 || DB.Model(&user).Association("Languages").Count() != 0 {
t.Errorf("Relations should be cleared") t.Errorf("Relations should be cleared")
} }
} }