mirror of https://github.com/go-gorm/gorm.git
Allow name of column to be customized to support self-referencing many2many fields.
This commit is contained in:
parent
c0359226dc
commit
8e7d807ebf
|
@ -279,3 +279,25 @@ func TestBelongsToWithPartialCustomizedColumn(t *testing.T) {
|
||||||
t.Errorf("should preload discount from coupon")
|
t.Errorf("should preload discount from coupon")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SelfReferencingUser struct {
|
||||||
|
gorm.Model
|
||||||
|
Friends []*SelfReferencingUser `gorm:"many2many:UserFriends;AssociationForeignKey:ID=friend_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelfReferencingMany2ManyColumn(t *testing.T) {
|
||||||
|
DB.DropTable(&SelfReferencingUser{}, "UserFriends")
|
||||||
|
DB.AutoMigrate(&SelfReferencingUser{})
|
||||||
|
|
||||||
|
friend := SelfReferencingUser{}
|
||||||
|
if err := DB.Create(&friend).Error; err != nil {
|
||||||
|
t.Errorf("no error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user := SelfReferencingUser{
|
||||||
|
Friends: []*SelfReferencingUser{&friend},
|
||||||
|
}
|
||||||
|
if err := DB.Create(&user).Error; err != nil {
|
||||||
|
t.Errorf("no error should happen, but got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -109,7 +109,24 @@ func (s JoinTableHandler) getSearchMap(db *DB, sources ...interface{}) map[strin
|
||||||
// Add create relationship in join table for source and destination
|
// Add create relationship in join table for source and destination
|
||||||
func (s JoinTableHandler) Add(handler JoinTableHandlerInterface, db *DB, source interface{}, destination interface{}) error {
|
func (s JoinTableHandler) Add(handler JoinTableHandlerInterface, db *DB, source interface{}, destination interface{}) error {
|
||||||
scope := db.NewScope("")
|
scope := db.NewScope("")
|
||||||
searchMap := s.getSearchMap(db, source, destination)
|
searchMap := map[string]interface{}{}
|
||||||
|
|
||||||
|
// getSearchMap() cannot be used here since the source and destination
|
||||||
|
// model types may be identical
|
||||||
|
|
||||||
|
sourceScope := db.NewScope(source)
|
||||||
|
for _, foreignKey := range s.Source.ForeignKeys {
|
||||||
|
if field, ok := sourceScope.FieldByName(foreignKey.AssociationDBName); ok {
|
||||||
|
searchMap[foreignKey.DBName] = field.Field.Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destinationScope := db.NewScope(destination)
|
||||||
|
for _, foreignKey := range s.Destination.ForeignKeys {
|
||||||
|
if field, ok := destinationScope.FieldByName(foreignKey.AssociationDBName); ok {
|
||||||
|
searchMap[foreignKey.DBName] = field.Field.Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var assignColumns, binVars, conditions []string
|
var assignColumns, binVars, conditions []string
|
||||||
var values []interface{}
|
var values []interface{}
|
||||||
|
|
|
@ -289,11 +289,24 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range associationForeignKeys {
|
for _, name := range associationForeignKeys {
|
||||||
|
|
||||||
|
// In order to allow self-referencing many2many tables, the name
|
||||||
|
// may be followed by "=" to allow renaming the column
|
||||||
|
parts := strings.Split(name, "=")
|
||||||
|
name = parts[0]
|
||||||
|
|
||||||
if field, ok := toScope.FieldByName(name); ok {
|
if field, ok := toScope.FieldByName(name); ok {
|
||||||
// association foreign keys (db names)
|
// association foreign keys (db names)
|
||||||
relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, field.DBName)
|
relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, field.DBName)
|
||||||
|
|
||||||
|
// If a new name was provided for the field, use it
|
||||||
|
name = field.DBName
|
||||||
|
if len(parts) > 1 {
|
||||||
|
name = parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
// join table foreign keys for association
|
// join table foreign keys for association
|
||||||
joinTableDBName := ToDBName(elemType.Name()) + "_" + field.DBName
|
joinTableDBName := ToDBName(elemType.Name()) + "_" + name
|
||||||
relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, joinTableDBName)
|
relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, joinTableDBName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue