2015-02-28 09:16:51 +03:00
package gorm_test
import (
"fmt"
2017-03-22 17:57:13 +03:00
"strconv"
2015-02-28 09:16:51 +03:00
"testing"
"time"
"github.com/jinzhu/gorm"
)
type Person struct {
Id int
Name string
Addresses [ ] * Address ` gorm:"many2many:person_addresses;" `
}
type PersonAddress struct {
2015-03-20 06:11:30 +03:00
gorm . JoinTableHandler
2015-02-28 09:16:51 +03:00
PersonID int
AddressID int
2016-01-10 16:33:15 +03:00
DeletedAt * time . Time
2015-02-28 09:16:51 +03:00
CreatedAt time . Time
}
2015-06-19 06:32:11 +03:00
func ( * PersonAddress ) Add ( handler gorm . JoinTableHandlerInterface , db * gorm . DB , foreignValue interface { } , associationValue interface { } ) error {
2017-03-22 17:57:13 +03:00
foreignPrimaryKey , _ := strconv . Atoi ( fmt . Sprint ( db . NewScope ( foreignValue ) . PrimaryKeyValue ( ) ) )
associationPrimaryKey , _ := strconv . Atoi ( fmt . Sprint ( db . NewScope ( associationValue ) . PrimaryKeyValue ( ) ) )
if result := db . Unscoped ( ) . Model ( & PersonAddress { } ) . Where ( map [ string ] interface { } {
"person_id" : foreignPrimaryKey ,
"address_id" : associationPrimaryKey ,
} ) . Update ( map [ string ] interface { } {
"person_id" : foreignPrimaryKey ,
"address_id" : associationPrimaryKey ,
2015-03-20 06:11:30 +03:00
"deleted_at" : gorm . Expr ( "NULL" ) ,
2017-03-22 17:57:13 +03:00
} ) . RowsAffected ; result == 0 {
return db . Create ( & PersonAddress {
PersonID : foreignPrimaryKey ,
AddressID : associationPrimaryKey ,
} ) . Error
}
return nil
2015-02-28 09:16:51 +03:00
}
2015-06-19 06:32:11 +03:00
func ( * PersonAddress ) Delete ( handler gorm . JoinTableHandlerInterface , db * gorm . DB , sources ... interface { } ) error {
2015-02-28 09:16:51 +03:00
return db . Delete ( & PersonAddress { } ) . Error
}
2015-06-19 06:32:11 +03:00
func ( pa * PersonAddress ) JoinWith ( handler gorm . JoinTableHandlerInterface , db * gorm . DB , source interface { } ) * gorm . DB {
2015-03-18 13:14:28 +03:00
table := pa . Table ( db )
2016-01-12 07:16:22 +03:00
return db . Joins ( "INNER JOIN person_addresses ON person_addresses.address_id = addresses.id" ) . Where ( fmt . Sprintf ( "%v.deleted_at IS NULL OR %v.deleted_at <= '0001-01-02'" , table , table ) )
2015-02-28 09:16:51 +03:00
}
func TestJoinTable ( t * testing . T ) {
DB . Exec ( "drop table person_addresses;" )
DB . AutoMigrate ( & Person { } )
2015-03-19 13:23:54 +03:00
DB . SetJoinTableHandler ( & Person { } , "Addresses" , & PersonAddress { } )
2015-02-28 09:16:51 +03:00
address1 := & Address { Address1 : "address 1" }
address2 := & Address { Address1 : "address 2" }
person := & Person { Name : "person" , Addresses : [ ] * Address { address1 , address2 } }
DB . Save ( person )
DB . Model ( person ) . Association ( "Addresses" ) . Delete ( address1 )
if DB . Find ( & [ ] PersonAddress { } , "person_id = ?" , person . Id ) . RowsAffected != 1 {
t . Errorf ( "Should found one address" )
}
2015-03-19 13:30:35 +03:00
if DB . Model ( person ) . Association ( "Addresses" ) . Count ( ) != 1 {
2015-02-28 09:16:51 +03:00
t . Errorf ( "Should found one address" )
}
if DB . Unscoped ( ) . Find ( & [ ] PersonAddress { } , "person_id = ?" , person . Id ) . RowsAffected != 2 {
t . Errorf ( "Found two addresses with Unscoped" )
}
if DB . Model ( person ) . Association ( "Addresses" ) . Clear ( ) ; DB . Model ( person ) . Association ( "Addresses" ) . Count ( ) != 0 {
t . Errorf ( "Should deleted all addresses" )
}
}
2017-06-14 11:49:39 +03:00
func TestEmbeddedMany2ManyRelationship ( t * testing . T ) {
type EmbeddedPerson struct {
ID int
Name string
Addresses [ ] * Address ` gorm:"many2many:person_addresses;" `
}
type NewPerson struct {
EmbeddedPerson
ExternalID uint
}
DB . Exec ( "drop table person_addresses;" )
DB . AutoMigrate ( & NewPerson { } )
address1 := & Address { Address1 : "address 1" }
address2 := & Address { Address1 : "address 2" }
person := & NewPerson { ExternalID : 100 , EmbeddedPerson : EmbeddedPerson { Name : "person" , Addresses : [ ] * Address { address1 , address2 } } }
if err := DB . Save ( person ) . Error ; err != nil {
t . Errorf ( "no error should return when save embedded many2many relationship, but got %v" , err )
}
if err := DB . Model ( person ) . Association ( "Addresses" ) . Delete ( address1 ) . Error ; err != nil {
t . Errorf ( "no error should return when delete embedded many2many relationship, but got %v" , err )
}
association := DB . Model ( person ) . Debug ( ) . Association ( "Addresses" )
if count := association . Count ( ) ; count != 1 || association . Error != nil {
t . Errorf ( "Should found one address, but got %v, error is %v" , count , association . Error )
}
if association . Clear ( ) ; association . Count ( ) != 0 {
t . Errorf ( "Should deleted all addresses" )
}
}