forked from go-gorm/gorm
-
-
Notifications
You must be signed in to change notification settings - Fork 195
/
join_table_test.go
117 lines (96 loc) · 3.7 KB
/
join_table_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package gorm_test
import (
"fmt"
"strconv"
"testing"
"time"
"github.com/jinzhu/gorm"
)
type Person struct {
Id int
Name string
Addresses []*Address `gorm:"many2many:person_addresses;"`
}
type PersonAddress struct {
gorm.JoinTableHandler
PersonID int
AddressID int
DeletedAt *time.Time
CreatedAt time.Time
}
func (*PersonAddress) Add(handler gorm.JoinTableHandlerInterface, db *gorm.DB, foreignValue interface{}, associationValue interface{}) error {
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,
"deleted_at": gorm.Expr("NULL"),
}).RowsAffected; result == 0 {
return db.Create(&PersonAddress{
PersonID: foreignPrimaryKey,
AddressID: associationPrimaryKey,
}).Error
}
return nil
}
func (*PersonAddress) Delete(handler gorm.JoinTableHandlerInterface, db *gorm.DB, sources ...interface{}) error {
return db.Delete(&PersonAddress{}).Error
}
func (pa *PersonAddress) JoinWith(handler gorm.JoinTableHandlerInterface, db *gorm.DB, source interface{}) *gorm.DB {
table := pa.Table(db)
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))
}
func TestJoinTable(t *testing.T) {
DB.Exec("drop table person_addresses;")
DB.AutoMigrate(&Person{})
DB.SetJoinTableHandler(&Person{}, "Addresses", &PersonAddress{})
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")
}
if DB.Model(person).Association("Addresses").Count() != 1 {
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")
}
}
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).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")
}
}