From 11346ae0662a4137a8a9ff5ac7129f2139a92d32 Mon Sep 17 00:00:00 2001 From: joe-at-startupmedia Date: Wed, 4 Oct 2017 08:19:16 +0000 Subject: [PATCH 1/3] Allows foreign keys to be saved without saving the assoication when specified #1628 --- callback_save.go | 53 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/callback_save.go b/callback_save.go index f4bc918e..ad4eda2f 100644 --- a/callback_save.go +++ b/callback_save.go @@ -11,35 +11,34 @@ func commitOrRollbackTransactionCallback(scope *Scope) { } func saveFieldAsAssociation(scope *Scope, field *Field) (bool, *Relationship) { - if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { - if value, ok := field.TagSettings["SAVE_ASSOCIATIONS"]; !ok || (value != "false" && value != "skip") { - if relationship := field.Relationship; relationship != nil { - return true, relationship - } - } - } - return false, nil + if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { + if value, ok := field.TagSettings["SAVE_ASSOCIATIONS"]; !ok || (value != "false" && value != "skip") { + return true, field.Relationship + } + return false, field.Relationship + } + return false, nil } func saveBeforeAssociationsCallback(scope *Scope) { - if !scope.shouldSaveAssociations() { - return - } - for _, field := range scope.Fields() { - if ok, relationship := saveFieldAsAssociation(scope, field); ok && relationship.Kind == "belongs_to" { - fieldValue := field.Field.Addr().Interface() - scope.Err(scope.NewDB().Save(fieldValue).Error) - if len(relationship.ForeignFieldNames) != 0 { - // set value's foreign key - for idx, fieldName := range relationship.ForeignFieldNames { - associationForeignName := relationship.AssociationForeignDBNames[idx] - if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok { - scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface())) - } - } - } - } - } + for _, field := range scope.Fields() { + ok, relationship := saveFieldAsAssociation(scope, field); + if relationship != nil && relationship.Kind == "belongs_to" { + fieldValue := field.Field.Addr().Interface() + if ok && scope.shouldSaveAssociations() { + scope.Err(scope.NewDB().Save(fieldValue).Error) + } + if len(relationship.ForeignFieldNames) != 0 { + // set value's foreign key + for idx, fieldName := range relationship.ForeignFieldNames { + associationForeignName := relationship.AssociationForeignDBNames[idx] + if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok { + scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface())) + } + } + } + } + } } func saveAfterAssociationsCallback(scope *Scope) { @@ -47,7 +46,7 @@ func saveAfterAssociationsCallback(scope *Scope) { return } for _, field := range scope.Fields() { - if ok, relationship := saveFieldAsAssociation(scope, field); ok && + if ok, relationship := saveFieldAsAssociation(scope, field); ok && relationship != nil && (relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") { value := field.Field From c8fb480e6b07a98f109b08fc0764a705f847bbfe Mon Sep 17 00:00:00 2001 From: joe-at-startupmedia Date: Tue, 10 Oct 2017 18:20:56 +0000 Subject: [PATCH 2/3] Formatting code with gomt --- callback_save.go | 50 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/callback_save.go b/callback_save.go index ad4eda2f..fa32c907 100644 --- a/callback_save.go +++ b/callback_save.go @@ -11,34 +11,34 @@ func commitOrRollbackTransactionCallback(scope *Scope) { } func saveFieldAsAssociation(scope *Scope, field *Field) (bool, *Relationship) { - if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { - if value, ok := field.TagSettings["SAVE_ASSOCIATIONS"]; !ok || (value != "false" && value != "skip") { - return true, field.Relationship - } - return false, field.Relationship - } - return false, nil + if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { + if value, ok := field.TagSettings["SAVE_ASSOCIATIONS"]; !ok || (value != "false" && value != "skip") { + return true, field.Relationship + } + return false, field.Relationship + } + return false, nil } func saveBeforeAssociationsCallback(scope *Scope) { - for _, field := range scope.Fields() { - ok, relationship := saveFieldAsAssociation(scope, field); - if relationship != nil && relationship.Kind == "belongs_to" { - fieldValue := field.Field.Addr().Interface() - if ok && scope.shouldSaveAssociations() { - scope.Err(scope.NewDB().Save(fieldValue).Error) - } - if len(relationship.ForeignFieldNames) != 0 { - // set value's foreign key - for idx, fieldName := range relationship.ForeignFieldNames { - associationForeignName := relationship.AssociationForeignDBNames[idx] - if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok { - scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface())) - } - } - } - } - } + for _, field := range scope.Fields() { + ok, relationship := saveFieldAsAssociation(scope, field) + if relationship != nil && relationship.Kind == "belongs_to" { + fieldValue := field.Field.Addr().Interface() + if ok && scope.shouldSaveAssociations() { + scope.Err(scope.NewDB().Save(fieldValue).Error) + } + if len(relationship.ForeignFieldNames) != 0 { + // set value's foreign key + for idx, fieldName := range relationship.ForeignFieldNames { + associationForeignName := relationship.AssociationForeignDBNames[idx] + if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok { + scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface())) + } + } + } + } + } } func saveAfterAssociationsCallback(scope *Scope) { From c82c9b224f7ec9ac3e6d876992d4222348f9a3ee Mon Sep 17 00:00:00 2001 From: Ezequiel Muns Date: Wed, 1 Nov 2017 18:45:08 +0100 Subject: [PATCH 3/3] Tests for saving foreign key when save_associations:false --- association_test.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/association_test.go b/association_test.go index c84f84ed..f37047d1 100644 --- a/association_test.go +++ b/association_test.go @@ -902,6 +902,20 @@ func TestSkipSaveAssociation(t *testing.T) { DB.Save(&User{Name: "jinzhu", Company: Company{Name: "skip_save_association"}}) if !DB.Where("name = ?", "skip_save_association").First(&Company{}).RecordNotFound() { - t.Errorf("Company skip_save_association should not been saved") + t.Errorf("Company skip_save_association should not have been saved") + } + + // if foreign key is set, this should be saved even if association isn't + company := Company{Name: "skip_save_association"} + DB.Save(&company) + company.Name = "skip_save_association_modified" + user := User{Name: "jinzhu", CompanyID: company.ID, Company: company} + DB.Save(&user) + + if !DB.Where("name = ?", "skip_save_association_modified").First(&Company{}).RecordNotFound() { + t.Errorf("Company skip_save_association should not have been updated") + } + if DB.Where("id = ? AND company_id = ?", user.ID, company.ID).First(&User{}).RecordNotFound() { + t.Errorf("User's foreign key should have been saved") } }