forked from mirror/gorm
Fix association Append for polymorphic
This commit is contained in:
parent
c88960b9b0
commit
e65f94b287
|
@ -26,7 +26,7 @@ func (association *Association) Find(value interface{}) *Association {
|
||||||
return association.setErr(association.Scope.db.Error)
|
return association.setErr(association.Scope.db.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (association *Association) Append(values ...interface{}) *Association {
|
func (association *Association) saveAssociations(values ...interface{}) *Association {
|
||||||
scope := association.Scope
|
scope := association.Scope
|
||||||
field := association.Field
|
field := association.Field
|
||||||
relationship := association.Field.Relationship
|
relationship := association.Field.Relationship
|
||||||
|
@ -81,6 +81,13 @@ func (association *Association) Append(values ...interface{}) *Association {
|
||||||
return association
|
return association
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (association *Association) Append(values ...interface{}) *Association {
|
||||||
|
if relationship := association.Field.Relationship; relationship.Kind == "has_one" {
|
||||||
|
return association.Replace(values...)
|
||||||
|
}
|
||||||
|
return association.saveAssociations(values...)
|
||||||
|
}
|
||||||
|
|
||||||
func (association *Association) Replace(values ...interface{}) *Association {
|
func (association *Association) Replace(values ...interface{}) *Association {
|
||||||
var (
|
var (
|
||||||
relationship = association.Field.Relationship
|
relationship = association.Field.Relationship
|
||||||
|
@ -91,7 +98,7 @@ func (association *Association) Replace(values ...interface{}) *Association {
|
||||||
|
|
||||||
// Append new values
|
// Append new values
|
||||||
association.Field.Set(reflect.Zero(association.Field.Field.Type()))
|
association.Field.Set(reflect.Zero(association.Field.Field.Type()))
|
||||||
association.Append(values...)
|
association.saveAssociations(values...)
|
||||||
|
|
||||||
// Belongs To
|
// Belongs To
|
||||||
if relationship.Kind == "belongs_to" {
|
if relationship.Kind == "belongs_to" {
|
||||||
|
@ -114,6 +121,10 @@ func (association *Association) Replace(values ...interface{}) *Association {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if relationship.PolymorphicDBName != "" {
|
||||||
|
newDB = newDB.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.PolymorphicDBName)), scope.TableName())
|
||||||
|
}
|
||||||
|
|
||||||
// Relations except new created
|
// Relations except new created
|
||||||
if len(values) > 0 {
|
if len(values) > 0 {
|
||||||
var newPrimaryKeys [][]interface{}
|
var newPrimaryKeys [][]interface{}
|
||||||
|
|
4
field.go
4
field.go
|
@ -42,6 +42,10 @@ func (field *Field) Set(value interface{}) error {
|
||||||
reflectValue = reflect.ValueOf(value)
|
reflectValue = reflect.ValueOf(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !reflectValue.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if reflectValue.Type().ConvertibleTo(field.Field.Type()) {
|
if reflectValue.Type().ConvertibleTo(field.Field.Type()) {
|
||||||
field.Field.Set(reflectValue.Convert(field.Field.Type()))
|
field.Field.Set(reflectValue.Convert(field.Field.Type()))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,7 +15,7 @@ func runMigration() {
|
||||||
DB.Exec(fmt.Sprintf("drop table %v;", table))
|
DB.Exec(fmt.Sprintf("drop table %v;", table))
|
||||||
}
|
}
|
||||||
|
|
||||||
values := []interface{}{&Product{}, &Email{}, &Address{}, &CreditCard{}, &Company{}, &Role{}, &Language{}, &HNPost{}, &EngadgetPost{}, &Animal{}, &User{}, &JoinTable{}, &Post{}, &Category{}, &Comment{}}
|
values := []interface{}{&Product{}, &Email{}, &Address{}, &CreditCard{}, &Company{}, &Role{}, &Language{}, &HNPost{}, &EngadgetPost{}, &Animal{}, &User{}, &JoinTable{}, &Post{}, &Category{}, &Comment{}, &Cat{}, &Dog{}, &Toy{}}
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
DB.DropTable(value)
|
DB.DropTable(value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package gorm_test
|
package gorm_test
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
type Cat struct {
|
type Cat struct {
|
||||||
Id int
|
Id int
|
||||||
|
@ -21,15 +26,30 @@ type Toy struct {
|
||||||
OwnerType string
|
OwnerType string
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPolymorphic(t *testing.T) {
|
var compareToys = func(toys []Toy, contents []string) bool {
|
||||||
DB.AutoMigrate(&Cat{})
|
var toyContents []string
|
||||||
DB.AutoMigrate(&Dog{})
|
for _, toy := range toys {
|
||||||
DB.AutoMigrate(&Toy{})
|
toyContents = append(toyContents, toy.Name)
|
||||||
|
}
|
||||||
|
sort.Strings(toyContents)
|
||||||
|
sort.Strings(contents)
|
||||||
|
return reflect.DeepEqual(toyContents, contents)
|
||||||
|
}
|
||||||
|
|
||||||
cat := Cat{Name: "Mr. Bigglesworth", Toy: Toy{Name: "cat nip"}}
|
func TestPolymorphic(t *testing.T) {
|
||||||
dog := Dog{Name: "Pluto", Toys: []Toy{Toy{Name: "orange ball"}, Toy{Name: "yellow ball"}}}
|
cat := Cat{Name: "Mr. Bigglesworth", Toy: Toy{Name: "cat toy"}}
|
||||||
|
dog := Dog{Name: "Pluto", Toys: []Toy{Toy{Name: "dog toy 1"}, Toy{Name: "dog toy 2"}}}
|
||||||
DB.Save(&cat).Save(&dog)
|
DB.Save(&cat).Save(&dog)
|
||||||
|
|
||||||
|
if DB.Model(&cat).Association("Toy").Count() != 1 {
|
||||||
|
t.Errorf("Cat's toys count should be 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
if DB.Model(&cat).Association("Toy").Count() != 1 {
|
||||||
|
t.Errorf("Dog's toys count should be 2")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query
|
||||||
var catToys []Toy
|
var catToys []Toy
|
||||||
if DB.Model(&cat).Related(&catToys, "Toy").RecordNotFound() {
|
if DB.Model(&cat).Related(&catToys, "Toy").RecordNotFound() {
|
||||||
t.Errorf("Did not find any has one polymorphic association")
|
t.Errorf("Did not find any has one polymorphic association")
|
||||||
|
@ -46,11 +66,52 @@ func TestPolymorphic(t *testing.T) {
|
||||||
t.Errorf("Should have found all polymorphic has many associations")
|
t.Errorf("Should have found all polymorphic has many associations")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var catToy Toy
|
||||||
|
DB.Model(&cat).Association("Toy").Find(&catToy)
|
||||||
|
if catToy.Name != cat.Toy.Name {
|
||||||
|
t.Errorf("Should find has one polymorphic association")
|
||||||
|
}
|
||||||
|
|
||||||
|
var dogToys1 []Toy
|
||||||
|
DB.Model(&dog).Association("Toys").Find(&dogToys1)
|
||||||
|
if !compareToys(dogToys1, []string{"dog toy 1", "dog toy 2"}) {
|
||||||
|
t.Errorf("Should find has many polymorphic association")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append
|
||||||
|
DB.Model(&cat).Association("Toy").Append(&Toy{
|
||||||
|
Name: "cat toy 2",
|
||||||
|
})
|
||||||
|
|
||||||
|
var catToy2 Toy
|
||||||
|
DB.Model(&cat).Association("Toy").Find(&catToy2)
|
||||||
|
if catToy2.Name != "cat toy 2" {
|
||||||
|
t.Errorf("Should update has one polymorphic association with Append")
|
||||||
|
}
|
||||||
|
|
||||||
if DB.Model(&cat).Association("Toy").Count() != 1 {
|
if DB.Model(&cat).Association("Toy").Count() != 1 {
|
||||||
t.Errorf("Should return one polymorphic has one association")
|
t.Errorf("Cat's toys count should be 1 after Append")
|
||||||
}
|
}
|
||||||
|
|
||||||
if DB.Model(&dog).Association("Toys").Count() != 2 {
|
if DB.Model(&dog).Association("Toys").Count() != 2 {
|
||||||
t.Errorf("Should return two polymorphic has many associations")
|
t.Errorf("Should return two polymorphic has many associations")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DB.Model(&dog).Association("Toys").Append(&Toy{
|
||||||
|
Name: "dog toy 3",
|
||||||
|
})
|
||||||
|
|
||||||
|
var dogToys2 []Toy
|
||||||
|
DB.Model(&dog).Association("Toys").Find(&dogToys2)
|
||||||
|
fmt.Println(dogToys2)
|
||||||
|
if !compareToys(dogToys2, []string{"dog toy 1", "dog toy 2", "dog toy 3"}) {
|
||||||
|
t.Errorf("Dog's toys should be updated with Append")
|
||||||
|
}
|
||||||
|
|
||||||
|
if DB.Model(&dog).Association("Toys").Count() != 3 {
|
||||||
|
t.Errorf("Should return three polymorphic has many associations")
|
||||||
|
}
|
||||||
|
// Replace
|
||||||
|
// Delete
|
||||||
|
// Clear
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue