(values ...interface{})
| 73 | } |
| 74 | |
| 75 | func (association *Association) Replace(values ...interface{}) error { |
| 76 | values = expandValues(values) |
| 77 | |
| 78 | if association.Error == nil { |
| 79 | reflectValue := association.DB.Statement.ReflectValue |
| 80 | rel := association.Relationship |
| 81 | |
| 82 | var oldBelongsToExpr clause.Expression |
| 83 | // we have to record the old BelongsTo value |
| 84 | if association.Unscope && rel.Type == schema.BelongsTo { |
| 85 | var foreignFields []*schema.Field |
| 86 | for _, ref := range rel.References { |
| 87 | if !ref.OwnPrimaryKey { |
| 88 | foreignFields = append(foreignFields, ref.ForeignKey) |
| 89 | } |
| 90 | } |
| 91 | if _, fvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, foreignFields); len(fvs) > 0 { |
| 92 | column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, fvs) |
| 93 | oldBelongsToExpr = clause.IN{Column: column, Values: values} |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | // save associations |
| 98 | if association.saveAssociation( /*clear*/ true, values...); association.Error != nil { |
| 99 | return association.Error |
| 100 | } |
| 101 | |
| 102 | // set old association's foreign key to null |
| 103 | switch rel.Type { |
| 104 | case schema.BelongsTo: |
| 105 | if len(values) == 0 { |
| 106 | updateMap := map[string]interface{}{} |
| 107 | switch reflectValue.Kind() { |
| 108 | case reflect.Slice, reflect.Array: |
| 109 | for i := 0; i < reflectValue.Len(); i++ { |
| 110 | association.Error = rel.Field.Set(association.DB.Statement.Context, reflectValue.Index(i), reflect.Zero(rel.Field.FieldType).Interface()) |
| 111 | } |
| 112 | case reflect.Struct: |
| 113 | association.Error = rel.Field.Set(association.DB.Statement.Context, reflectValue, reflect.Zero(rel.Field.FieldType).Interface()) |
| 114 | } |
| 115 | |
| 116 | for _, ref := range rel.References { |
| 117 | updateMap[ref.ForeignKey.DBName] = nil |
| 118 | } |
| 119 | |
| 120 | association.Error = association.DB.UpdateColumns(updateMap).Error |
| 121 | } |
| 122 | if association.Unscope && oldBelongsToExpr != nil { |
| 123 | association.Error = association.DB.Model(nil).Where(oldBelongsToExpr).Delete(reflect.New(rel.FieldSchema.ModelType).Interface()).Error |
| 124 | } |
| 125 | case schema.HasOne, schema.HasMany: |
| 126 | var ( |
| 127 | primaryFields []*schema.Field |
| 128 | foreignKeys []string |
| 129 | updateMap = map[string]interface{}{} |
| 130 | relValues = schema.GetRelationsValues(association.DB.Statement.Context, reflectValue, []*schema.Relationship{rel}) |
| 131 | modelValue = reflect.New(rel.FieldSchema.ModelType).Interface() |
| 132 | tx = association.DB.Model(modelValue) |
no test coverage detected