Add Append support for other associations
This commit is contained in:
		
							parent
							
								
									4677215ef4
								
							
						
					
					
						commit
						0ce635cc67
					
				@ -29,42 +29,53 @@ func (association *Association) Find(value interface{}) *Association {
 | 
				
			|||||||
func (association *Association) Append(values ...interface{}) *Association {
 | 
					func (association *Association) Append(values ...interface{}) *Association {
 | 
				
			||||||
	scope := association.Scope
 | 
						scope := association.Scope
 | 
				
			||||||
	field := association.Field
 | 
						field := association.Field
 | 
				
			||||||
 | 
						relationship := association.Field.Relationship
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	createJoinTable := func(reflectValue reflect.Value) {
 | 
						saveAssociation := func(reflectValue reflect.Value) {
 | 
				
			||||||
		var value = reflectValue.Interface()
 | 
							// value has to been pointer
 | 
				
			||||||
		if reflectValue.Kind() != reflect.Ptr {
 | 
							if reflectValue.Kind() != reflect.Ptr {
 | 
				
			||||||
			reflectPtr := reflect.New(reflectValue.Type())
 | 
								reflectPtr := reflect.New(reflectValue.Type())
 | 
				
			||||||
			reflectPtr.Elem().Set(reflectValue)
 | 
								reflectPtr.Elem().Set(reflectValue)
 | 
				
			||||||
			value = reflectPtr.Interface()
 | 
								reflectValue = reflectPtr
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if scope.New(value).PrimaryKeyZero() {
 | 
							// value has to been saved
 | 
				
			||||||
			scope.NewDB().Save(value)
 | 
							if scope.New(reflectValue.Interface()).PrimaryKeyZero() {
 | 
				
			||||||
 | 
								scope.NewDB().Save(reflectValue.Interface())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		relationship := association.Field.Relationship
 | 
							// Assign Fields
 | 
				
			||||||
		association.setErr(relationship.JoinTableHandler.Add(relationship.JoinTableHandler, scope.NewDB(), scope.Value, value))
 | 
							fieldType := field.Field.Type()
 | 
				
			||||||
 | 
							if reflectValue.Type().AssignableTo(fieldType) {
 | 
				
			||||||
 | 
								field.Set(reflectValue)
 | 
				
			||||||
 | 
							} else if reflectValue.Type().Elem().AssignableTo(fieldType) {
 | 
				
			||||||
 | 
								field.Set(reflectValue.Elem())
 | 
				
			||||||
 | 
							} else if fieldType.Kind() == reflect.Slice {
 | 
				
			||||||
 | 
								if reflectValue.Type().AssignableTo(fieldType.Elem()) {
 | 
				
			||||||
 | 
									field.Set(reflect.Append(field.Field, reflectValue))
 | 
				
			||||||
 | 
								} else if reflectValue.Type().Elem().AssignableTo(fieldType.Elem()) {
 | 
				
			||||||
 | 
									field.Set(reflect.Append(field.Field, reflectValue.Elem()))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		result := reflect.ValueOf(value)
 | 
							if relationship.Kind == "many_to_many" {
 | 
				
			||||||
		fieldElemType := field.Field.Type().Elem()
 | 
								association.setErr(relationship.JoinTableHandler.Add(relationship.JoinTableHandler, scope.NewDB(), scope.Value, reflectValue.Interface()))
 | 
				
			||||||
		if result.Type().AssignableTo(fieldElemType) {
 | 
							} else {
 | 
				
			||||||
			field.Set(reflect.Append(field.Field, result))
 | 
								association.setErr(scope.NewDB().Select(field.Name).Save(scope.Value).Error)
 | 
				
			||||||
		} else if result.Type().Elem().AssignableTo(fieldElemType) {
 | 
					 | 
				
			||||||
			field.Set(reflect.Append(field.Field, result.Elem()))
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, value := range values {
 | 
						for _, value := range values {
 | 
				
			||||||
		reflectValue := reflect.Indirect(reflect.ValueOf(value))
 | 
							reflectValue := reflect.ValueOf(value)
 | 
				
			||||||
 | 
							indirectReflectValue := reflect.Indirect(reflectValue)
 | 
				
			||||||
		if reflectValue.Kind() == reflect.Struct {
 | 
							if indirectReflectValue.Kind() == reflect.Struct {
 | 
				
			||||||
			createJoinTable(reflectValue)
 | 
								saveAssociation(reflectValue)
 | 
				
			||||||
		} else if reflectValue.Kind() == reflect.Slice {
 | 
							} else if indirectReflectValue.Kind() == reflect.Slice {
 | 
				
			||||||
			for i := 0; i < reflectValue.Len(); i++ {
 | 
								for i := 0; i < indirectReflectValue.Len(); i++ {
 | 
				
			||||||
				createJoinTable(reflectValue.Index(i))
 | 
									saveAssociation(indirectReflectValue.Index(i))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			association.setErr(errors.New("invalid association type"))
 | 
								association.setErr(errors.New("invalid value type"))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return association
 | 
						return association
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,66 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestHasOne(t *testing.T) {
 | 
				
			||||||
 | 
						DB.DropTable(Category{}, Post{})
 | 
				
			||||||
 | 
						DB.CreateTable(Category{}, Post{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						post := Post{
 | 
				
			||||||
 | 
							Title:        "post 1",
 | 
				
			||||||
 | 
							Body:         "body 1",
 | 
				
			||||||
 | 
							Category:     Category{Name: "Category 1"},
 | 
				
			||||||
 | 
							MainCategory: Category{Name: "Main Category 1"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := DB.Save(&post).Error; err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Got errors when save post", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Query
 | 
				
			||||||
 | 
						var category Category
 | 
				
			||||||
 | 
						DB.Model(&post).Association("Category").Find(&category)
 | 
				
			||||||
 | 
						if category.Name != "Category 1" {
 | 
				
			||||||
 | 
							t.Errorf("Query has one relations with Association")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var category1 Category
 | 
				
			||||||
 | 
						DB.Model(&post).Related(&category1)
 | 
				
			||||||
 | 
						if category1.Name != "Category 1" {
 | 
				
			||||||
 | 
							t.Errorf("Query has one relations with Related")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Append
 | 
				
			||||||
 | 
						var category2 = Category{
 | 
				
			||||||
 | 
							Name: "Category 2",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						DB.Model(&post).Association("Category").Append(&category2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if category2.Id == 0 {
 | 
				
			||||||
 | 
							t.Errorf("Category should has ID when created with Append")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var category21 Category
 | 
				
			||||||
 | 
						DB.Model(&post).Related(&category21)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if category21.Name != "Category 2" {
 | 
				
			||||||
 | 
							t.Errorf("Category should be updated with Append")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Replace
 | 
				
			||||||
 | 
						// DB.Model(&post).Association("Category").Replace(&Category{
 | 
				
			||||||
 | 
						// 	Name: "Category 3",
 | 
				
			||||||
 | 
						// })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// var category3 Category
 | 
				
			||||||
 | 
						// DB.Model(&post).Related(&category3)
 | 
				
			||||||
 | 
						// if category3.Name != "Category 3" {
 | 
				
			||||||
 | 
						// 	t.Errorf("Category should be updated with Replace")
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delete
 | 
				
			||||||
 | 
						// Clear
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestHasOneAndHasManyAssociation(t *testing.T) {
 | 
					func TestHasOneAndHasManyAssociation(t *testing.T) {
 | 
				
			||||||
	DB.DropTable(Category{}, Post{}, Comment{})
 | 
						DB.DropTable(Category{}, Post{}, Comment{})
 | 
				
			||||||
	DB.CreateTable(Category{}, Post{}, Comment{})
 | 
						DB.CreateTable(Category{}, Post{}, Comment{})
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user