Refactor association Delete
This commit is contained in:
		
							parent
							
								
									e65f94b287
								
							
						
					
					
						commit
						300b74f15f
					
				@ -169,37 +169,30 @@ func (association *Association) Delete(values ...interface{}) *Association {
 | 
				
			|||||||
		return association
 | 
							return association
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var deletingResourcePrimaryFieldNames, deletingResourcePrimaryDBNames []string
 | 
				
			||||||
 | 
						for _, field := range scope.New(reflect.New(field.Type()).Interface()).Fields() {
 | 
				
			||||||
 | 
							if field.IsPrimaryKey {
 | 
				
			||||||
 | 
								deletingResourcePrimaryFieldNames = append(deletingResourcePrimaryFieldNames, field.Name)
 | 
				
			||||||
 | 
								deletingResourcePrimaryDBNames = append(deletingResourcePrimaryDBNames, field.DBName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						deletingPrimaryKeys := association.getPrimaryKeys(deletingResourcePrimaryFieldNames, values...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if relationship.Kind == "many_to_many" {
 | 
						if relationship.Kind == "many_to_many" {
 | 
				
			||||||
		// many to many
 | 
							// source value's foreign keys
 | 
				
			||||||
		// current value's foreign keys
 | 
					 | 
				
			||||||
		for idx, foreignKey := range relationship.ForeignDBNames {
 | 
							for idx, foreignKey := range relationship.ForeignDBNames {
 | 
				
			||||||
			if field, ok := scope.FieldByName(relationship.ForeignFieldNames[idx]); ok {
 | 
								if field, ok := scope.FieldByName(relationship.ForeignFieldNames[idx]); ok {
 | 
				
			||||||
				newDB = newDB.Where(fmt.Sprintf("%v = ?", scope.Quote(foreignKey)), field.Field.Interface())
 | 
									newDB = newDB.Where(fmt.Sprintf("%v = ?", scope.Quote(foreignKey)), field.Field.Interface())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// deleting value's foreign keys
 | 
							// association value's foreign keys
 | 
				
			||||||
		primaryKeys := association.getPrimaryKeys(relationship.AssociationForeignFieldNames, values...)
 | 
							deletingPrimaryKeys := association.getPrimaryKeys(relationship.AssociationForeignFieldNames, values...)
 | 
				
			||||||
		sql := fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.AssociationForeignDBNames), toQueryMarks(primaryKeys))
 | 
							sql := fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.AssociationForeignDBNames), toQueryMarks(deletingPrimaryKeys))
 | 
				
			||||||
		newDB = newDB.Where(sql, toQueryValues(primaryKeys)...)
 | 
							newDB = newDB.Where(sql, toQueryValues(deletingPrimaryKeys)...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := relationship.JoinTableHandler.Delete(relationship.JoinTableHandler, newDB, relationship); err == nil {
 | 
							association.setErr(relationship.JoinTableHandler.Delete(relationship.JoinTableHandler, newDB, relationship))
 | 
				
			||||||
			leftValues := reflect.Zero(association.Field.Field.Type())
 | 
					 | 
				
			||||||
			for i := 0; i < association.Field.Field.Len(); i++ {
 | 
					 | 
				
			||||||
				reflectValue := association.Field.Field.Index(i)
 | 
					 | 
				
			||||||
				primaryKey := association.getPrimaryKeys(relationship.ForeignFieldNames, reflectValue.Interface())[0]
 | 
					 | 
				
			||||||
				var included = false
 | 
					 | 
				
			||||||
				for _, pk := range primaryKeys {
 | 
					 | 
				
			||||||
					if equalAsString(primaryKey, pk) {
 | 
					 | 
				
			||||||
						included = true
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if !included {
 | 
					 | 
				
			||||||
					leftValues = reflect.Append(leftValues, reflectValue)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			association.Field.Set(leftValues)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		var foreignKeyMap = map[string]interface{}{}
 | 
							var foreignKeyMap = map[string]interface{}{}
 | 
				
			||||||
		for _, foreignKey := range relationship.ForeignDBNames {
 | 
							for _, foreignKey := range relationship.ForeignDBNames {
 | 
				
			||||||
@ -225,23 +218,45 @@ func (association *Association) Delete(values ...interface{}) *Association {
 | 
				
			|||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// only include those deleting relations
 | 
								// only include those deleting relations
 | 
				
			||||||
			var primaryFieldNames, primaryFieldDBNames []string
 | 
					 | 
				
			||||||
			for _, field := range scope.New(reflect.New(field.Type()).Interface()).Fields() {
 | 
					 | 
				
			||||||
				if field.IsPrimaryKey {
 | 
					 | 
				
			||||||
					primaryFieldNames = append(primaryFieldNames, field.Name)
 | 
					 | 
				
			||||||
					primaryFieldDBNames = append(primaryFieldDBNames, field.DBName)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			relationsPrimaryKeys := association.getPrimaryKeys(primaryFieldNames, values...)
 | 
					 | 
				
			||||||
			newDB = newDB.Where(
 | 
								newDB = newDB.Where(
 | 
				
			||||||
				fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, primaryFieldDBNames), toQueryMarks(relationsPrimaryKeys)),
 | 
									fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, deletingResourcePrimaryDBNames), toQueryMarks(deletingPrimaryKeys)),
 | 
				
			||||||
				toQueryValues(relationsPrimaryKeys)...,
 | 
									toQueryValues(deletingPrimaryKeys)...,
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// set matched relation's foreign key to be null
 | 
								// set matched relation's foreign key to be null
 | 
				
			||||||
			fieldValue := reflect.New(association.Field.Field.Type()).Interface()
 | 
								fieldValue := reflect.New(association.Field.Field.Type()).Interface()
 | 
				
			||||||
			newDB.Model(fieldValue).UpdateColumn(foreignKeyMap)
 | 
								association.setErr(newDB.Model(fieldValue).UpdateColumn(foreignKeyMap).Error)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Remove deleted records from field
 | 
				
			||||||
 | 
						if association.Error == nil {
 | 
				
			||||||
 | 
							if association.Field.Field.Kind() == reflect.Slice {
 | 
				
			||||||
 | 
								leftValues := reflect.Zero(association.Field.Field.Type())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for i := 0; i < association.Field.Field.Len(); i++ {
 | 
				
			||||||
 | 
									reflectValue := association.Field.Field.Index(i)
 | 
				
			||||||
 | 
									primaryKey := association.getPrimaryKeys(deletingResourcePrimaryFieldNames, reflectValue.Interface())[0]
 | 
				
			||||||
 | 
									var included = false
 | 
				
			||||||
 | 
									for _, pk := range deletingPrimaryKeys {
 | 
				
			||||||
 | 
										if equalAsString(primaryKey, pk) {
 | 
				
			||||||
 | 
											included = true
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if !included {
 | 
				
			||||||
 | 
										leftValues = reflect.Append(leftValues, reflectValue)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								association.Field.Set(leftValues)
 | 
				
			||||||
 | 
							} else if association.Field.Field.Kind() == reflect.Struct {
 | 
				
			||||||
 | 
								for _, pk := range deletingPrimaryKeys {
 | 
				
			||||||
 | 
									primaryKey := association.getPrimaryKeys(deletingResourcePrimaryFieldNames, association.Field.Field)[0]
 | 
				
			||||||
 | 
									if equalAsString(primaryKey, pk) {
 | 
				
			||||||
 | 
										association.Field.Set(reflect.Zero(association.Field.Field.Type()))
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
package gorm_test
 | 
					package gorm_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
@ -103,7 +102,6 @@ func TestPolymorphic(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var dogToys2 []Toy
 | 
						var dogToys2 []Toy
 | 
				
			||||||
	DB.Model(&dog).Association("Toys").Find(&dogToys2)
 | 
						DB.Model(&dog).Association("Toys").Find(&dogToys2)
 | 
				
			||||||
	fmt.Println(dogToys2)
 | 
					 | 
				
			||||||
	if !compareToys(dogToys2, []string{"dog toy 1", "dog toy 2", "dog toy 3"}) {
 | 
						if !compareToys(dogToys2, []string{"dog toy 1", "dog toy 2", "dog toy 3"}) {
 | 
				
			||||||
		t.Errorf("Dog's toys should be updated with Append")
 | 
							t.Errorf("Dog's toys should be updated with Append")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -111,7 +109,111 @@ func TestPolymorphic(t *testing.T) {
 | 
				
			|||||||
	if DB.Model(&dog).Association("Toys").Count() != 3 {
 | 
						if DB.Model(&dog).Association("Toys").Count() != 3 {
 | 
				
			||||||
		t.Errorf("Should return three polymorphic has many associations")
 | 
							t.Errorf("Should return three polymorphic has many associations")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Replace
 | 
						// Replace
 | 
				
			||||||
 | 
						DB.Model(&cat).Association("Toy").Replace(&Toy{
 | 
				
			||||||
 | 
							Name: "cat toy 3",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var catToy3 Toy
 | 
				
			||||||
 | 
						DB.Model(&cat).Association("Toy").Find(&catToy3)
 | 
				
			||||||
 | 
						if catToy3.Name != "cat toy 3" {
 | 
				
			||||||
 | 
							t.Errorf("Should update has one polymorphic association with Replace")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&cat).Association("Toy").Count() != 1 {
 | 
				
			||||||
 | 
							t.Errorf("Cat's toys count should be 1 after Replace")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 3 {
 | 
				
			||||||
 | 
							t.Errorf("Should return three polymorphic has many associations")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DB.Model(&dog).Association("Toys").Replace(&Toy{
 | 
				
			||||||
 | 
							Name: "dog toy 4",
 | 
				
			||||||
 | 
						}, []Toy{
 | 
				
			||||||
 | 
							{Name: "dog toy 5"}, {Name: "dog toy 6"}, {Name: "dog toy 7"},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var dogToys3 []Toy
 | 
				
			||||||
 | 
						DB.Model(&dog).Association("Toys").Find(&dogToys3)
 | 
				
			||||||
 | 
						if !compareToys(dogToys3, []string{"dog toy 4", "dog toy 5", "dog toy 6", "dog toy 7"}) {
 | 
				
			||||||
 | 
							t.Errorf("Dog's toys should be updated with Replace")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 4 {
 | 
				
			||||||
 | 
							t.Errorf("Should return three polymorphic has many associations")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete
 | 
						// Delete
 | 
				
			||||||
 | 
						DB.Model(&cat).Association("Toy").Delete(&catToy2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var catToy4 Toy
 | 
				
			||||||
 | 
						DB.Model(&cat).Association("Toy").Find(&catToy4)
 | 
				
			||||||
 | 
						if catToy4.Name != "cat toy 3" {
 | 
				
			||||||
 | 
							t.Errorf("Should not update has one polymorphic association when Delete a unrelated Toy")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&cat).Association("Toy").Count() != 1 {
 | 
				
			||||||
 | 
							t.Errorf("Cat's toys count should be 1")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 4 {
 | 
				
			||||||
 | 
							t.Errorf("Dog's toys count should be 4")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DB.Model(&cat).Association("Toy").Delete(&catToy3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !DB.Model(&cat).Related(&Toy{}, "Toy").RecordNotFound() {
 | 
				
			||||||
 | 
							t.Errorf("Toy should be deleted with Delete")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&cat).Association("Toy").Count() != 0 {
 | 
				
			||||||
 | 
							t.Errorf("Cat's toys count should be 0 after Delete")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 4 {
 | 
				
			||||||
 | 
							t.Errorf("Dog's toys count should not be changed when delete cat's toy")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DB.Model(&dog).Association("Toys").Delete(&dogToys2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 4 {
 | 
				
			||||||
 | 
							t.Errorf("Dog's toys count should not be changed when delete unrelated toys")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DB.Model(&dog).Association("Toys").Delete(&dogToys3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 0 {
 | 
				
			||||||
 | 
							t.Errorf("Dog's toys count should be deleted with Delete")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Clear
 | 
						// Clear
 | 
				
			||||||
 | 
						DB.Model(&cat).Association("Toy").Append(&Toy{
 | 
				
			||||||
 | 
							Name: "cat toy 2",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&cat).Association("Toy").Count() != 1 {
 | 
				
			||||||
 | 
							t.Errorf("Cat's toys should be added with Append")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DB.Model(&cat).Association("Toy").Clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&cat).Association("Toy").Count() != 0 {
 | 
				
			||||||
 | 
							t.Errorf("Cat's toys should be cleared with Clear")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DB.Model(&dog).Association("Toys").Append(&Toy{
 | 
				
			||||||
 | 
							Name: "dog toy 8",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 1 {
 | 
				
			||||||
 | 
							t.Errorf("Dog's toys should be added with Append")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DB.Model(&dog).Association("Toys").Clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if DB.Model(&dog).Association("Toys").Count() != 0 {
 | 
				
			||||||
 | 
							t.Errorf("Dog's toys should be cleared with Clear")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user