From 1bfa31fa7f2744983e69ae38ac3106f57edb35e5 Mon Sep 17 00:00:00 2001 From: black Date: Sun, 23 Apr 2023 17:15:30 +0800 Subject: [PATCH] work only on has association --- association.go | 19 ++------ tests/associations_has_many_test.go | 74 +++++++++++++++++++++++++++++ tests/associations_test.go | 73 ---------------------------- 3 files changed, 79 insertions(+), 87 deletions(-) diff --git a/association.go b/association.go index f3a11277..e17f863d 100644 --- a/association.go +++ b/association.go @@ -85,6 +85,7 @@ func (association *Association) Replace(values ...interface{}) error { switch rel.Type { case schema.BelongsTo: if len(values) == 0 { + updateMap := map[string]interface{}{} switch reflectValue.Kind() { case reflect.Slice, reflect.Array: for i := 0; i < reflectValue.Len(); i++ { @@ -94,16 +95,10 @@ func (association *Association) Replace(values ...interface{}) error { association.Error = rel.Field.Set(association.DB.Statement.Context, reflectValue, reflect.Zero(rel.Field.FieldType).Interface()) } - if association.Unscope { - modelValue := reflect.New(rel.FieldSchema.ModelType).Interface() - association.Error = association.DB.Delete(modelValue).Error - } else { - updateMap := map[string]interface{}{} - for _, ref := range rel.References { - updateMap[ref.ForeignKey.DBName] = nil - } - association.Error = association.DB.UpdateColumns(updateMap).Error + for _, ref := range rel.References { + updateMap[ref.ForeignKey.DBName] = nil } + association.Error = association.DB.UpdateColumns(updateMap).Error } case schema.HasOne, schema.HasMany: var ( @@ -216,11 +211,7 @@ func (association *Association) Delete(values ...interface{}) error { relColumn, relValues := schema.ToQueryValues(rel.Schema.Table, foreignKeys, rvs) conds = append(conds, clause.IN{Column: relColumn, Values: relValues}) - if association.Unscope { - association.Error = tx.Clauses(conds...).Delete(model).Error - } else { - association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error - } + association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error case schema.HasOne, schema.HasMany: model := reflect.New(rel.FieldSchema.ModelType).Interface() tx := association.DB.Model(model) diff --git a/tests/associations_has_many_test.go b/tests/associations_has_many_test.go index 002ae636..c31c4b40 100644 --- a/tests/associations_has_many_test.go +++ b/tests/associations_has_many_test.go @@ -3,6 +3,7 @@ package tests_test import ( "testing" + "gorm.io/gorm" . "gorm.io/gorm/utils/tests" ) @@ -471,3 +472,76 @@ func TestPolymorphicHasManyAssociationForSlice(t *testing.T) { DB.Model(&users).Association("Toys").Clear() AssertAssociationCount(t, users, "Toys", 0, "After Clear") } + +func TestHasManyAssociationUnscoped(t *testing.T) { + type ItemContent struct { + gorm.Model + ItemID uint `gorm:"not null"` + Name string `gorm:"not null;type:varchar(50)"` + LanguageCode string `gorm:"not null;type:varchar(2)"` + } + type Item struct { + gorm.Model + Logo string `gorm:"not null;type:varchar(50)"` + Contents []ItemContent `gorm:"foreignKey:ItemID"` + } + + tx := DB.Session(&gorm.Session{}) + tx.Migrator().DropTable(&ItemContent{}, &Item{}) + tx.AutoMigrate(&ItemContent{}, &Item{}) + + item := Item{ + Logo: "logo", + Contents: []ItemContent{ + {Name: "name", LanguageCode: "en"}, + {Name: "ar name", LanguageCode: "ar"}, + }, + } + if err := tx.Create(&item).Error; err != nil { + t.Fatalf("failed to create items, got error: %v", err) + } + + // test Replace + if err := tx.Model(&item).Association("Contents").Unscoped().Replace([]ItemContent{ + {Name: "updated name", LanguageCode: "en"}, + {Name: "ar updated name", LanguageCode: "ar"}, + {Name: "le nom", LanguageCode: "fr"}, + }); err != nil { + t.Errorf("failed to replace item content, got error: %v", err) + } + + if count := tx.Model(&item).Association("Contents").Count(); count != 3 { + t.Errorf("expected %d contents, got %d", 3, count) + } + + var contents []ItemContent + if err := tx.Find(&contents).Error; err != nil { + t.Errorf("failed to find contents, got error: %v", err) + } + if len(contents) != 3 { + t.Errorf("expected %d contents, got %d", 3, len(contents)) + } + + // test delete + if err := tx.Model(&item).Association("Contents").Unscoped().Delete(&contents[0]); err != nil { + t.Errorf("failed to delete Contents, got error: %v", err) + } + if count := tx.Model(&item).Association("Contents").Count(); count != 2 { + t.Errorf("expected %d contents, got %d", 2, count) + } + + // test clear + if err := tx.Model(&item).Association("Contents").Unscoped().Clear(); err != nil { + t.Errorf("failed to clear contents association, got error: %v", err) + } + if count := tx.Model(&item).Association("Contents").Count(); count != 0 { + t.Errorf("expected %d contents, got %d", 0, count) + } + + if err := tx.Find(&contents).Error; err != nil { + t.Errorf("failed to find contents, got error: %v", err) + } + if len(contents) != 0 { + t.Errorf("expected %d contents, got %d", 0, len(contents)) + } +} diff --git a/tests/associations_test.go b/tests/associations_test.go index 15505a20..4e8862e5 100644 --- a/tests/associations_test.go +++ b/tests/associations_test.go @@ -394,76 +394,3 @@ func TestAssociationEmptyPrimaryKey(t *testing.T) { AssertEqual(t, result, user) } - -func TestAssociationUnscoped(t *testing.T) { - type ItemContent struct { - gorm.Model - ItemID uint `gorm:"not null"` - Name string `gorm:"not null;type:varchar(50)"` - LanguageCode string `gorm:"not null;type:varchar(2)"` - } - type Item struct { - gorm.Model - Logo string `gorm:"not null;type:varchar(50)"` - Contents []ItemContent `gorm:"foreignKey:ItemID"` - } - - tx := DB.Session(&gorm.Session{}) - tx.Migrator().DropTable(&ItemContent{}, &Item{}) - tx.AutoMigrate(&ItemContent{}, &Item{}) - - item := Item{ - Logo: "logo", - Contents: []ItemContent{ - {Name: "name", LanguageCode: "en"}, - {Name: "ar name", LanguageCode: "ar"}, - }, - } - if err := tx.Create(&item).Error; err != nil { - t.Fatalf("failed to create items, got error: %v", err) - } - - // test Replace - if err := tx.Model(&item).Association("Contents").Unscoped().Replace([]ItemContent{ - {Name: "updated name", LanguageCode: "en"}, - {Name: "ar updated name", LanguageCode: "ar"}, - {Name: "le nom", LanguageCode: "fr"}, - }); err != nil { - t.Errorf("failed to replace item content, got error: %v", err) - } - - if count := tx.Model(&item).Association("Contents").Count(); count != 3 { - t.Errorf("expected %d contents, got %d", 3, count) - } - - var contents []ItemContent - if err := tx.Find(&contents).Error; err != nil { - t.Errorf("failed to find contents, got error: %v", err) - } - if len(contents) != 3 { - t.Errorf("expected 3 contents, got %d", len(contents)) - } - - // test delete - if err := tx.Model(&item).Association("Contents").Unscoped().Delete(&contents[0]); err != nil { - t.Errorf("failed to delete Contents, got error: %v", err) - } - if count := tx.Model(&item).Association("Contents").Count(); count != 2 { - t.Errorf("expected %d contents, got %d", 2, count) - } - - // test clear - if err := tx.Model(&item).Association("Contents").Unscoped().Clear(); err != nil { - t.Errorf("failed to clear contents association, got error: %v", err) - } - if count := tx.Model(&item).Association("Contents").Count(); count != 0 { - t.Errorf("expected %d contents, got %d", 0, count) - } - - if err := tx.Find(&contents).Error; err != nil { - t.Errorf("failed to find contents, got error: %v", err) - } - if len(contents) != 0 { - t.Errorf("expected %d contents, got %d", 0, len(contents)) - } -}