123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- 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")
- }
- }
|