From efd3b7678b0e63d55cb861f5e21007563b0046c7 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Wed, 30 Jul 2014 16:22:26 +0800 Subject: [PATCH] Be able to find many to many relations --- association.go | 54 ++++++++++++++++++++++++++++++++++++++++----- association_test.go | 2 +- migration_test.go | 2 +- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/association.go b/association.go index 7e0bc31c..dcf5803f 100644 --- a/association.go +++ b/association.go @@ -1,25 +1,67 @@ package gorm +import ( + "errors" + "fmt" + "reflect" +) + type Association struct { Scope *Scope Column string + Error error } -func (*Association) Find(value interface{}) { +func (association *Association) Find(value interface{}) *Association { + scope := association.Scope + primaryKey := scope.PrimaryKeyValue() + if reflect.DeepEqual(reflect.ValueOf(primaryKey), reflect.Zero(reflect.ValueOf(primaryKey).Type())) { + association.Error = errors.New("primary key can't be nil") + } + + scopeType := scope.IndirectValue().Type() + if f, ok := scopeType.FieldByName(SnakeToUpperCamel(association.Column)); ok { + field := scope.fieldFromStruct(f) + joinTable := field.JoinTable + if joinTable != nil && joinTable.foreignKey != "" { + if joinTable.joinTable != "" { + newScope := scope.New(value) + joinSql := fmt.Sprintf( + "INNER JOIN %v ON %v.%v = %v.%v", + scope.Quote(joinTable.joinTable), + scope.Quote(joinTable.joinTable), + scope.Quote(ToSnake(joinTable.associationForeignKey)), + newScope.QuotedTableName(), + scope.Quote(newScope.PrimaryKey())) + whereSql := fmt.Sprintf("%v.%v = ?", scope.Quote(joinTable.joinTable), scope.Quote(ToSnake(joinTable.foreignKey))) + scope.db.Joins(joinSql).Where(whereSql, primaryKey).Find(value) + } else { + } + } else { + association.Error = errors.New(fmt.Sprintf("invalid association %v for %v", association.Column, scopeType)) + } + } else { + association.Error = errors.New(fmt.Sprintf("%v doesn't have column %v", scopeType, association.Column)) + } + return association } -func (*Association) Append(values interface{}) { +func (association *Association) Append(values interface{}) *Association { + return association } -func (*Association) Delete(value interface{}) { +func (association *Association) Delete(value interface{}) *Association { + return association } -func (*Association) Clear(value interface{}) { +func (association *Association) Clear(value interface{}) *Association { + return association } -func (*Association) Replace(values interface{}) { +func (association *Association) Replace(values interface{}) *Association { + return association } -func (*Association) Count(values interface{}) int { +func (association *Association) Count(values interface{}) int { return 0 } diff --git a/association_test.go b/association_test.go index e2dd8142..a1b94b07 100644 --- a/association_test.go +++ b/association_test.go @@ -140,7 +140,7 @@ func TestManyToMany(t *testing.T) { newLanguages = []Language{} db.Model(&user).Association("Languages").Find(&newLanguages) if len(newLanguages) != 3 { - t.Errorf("Query many to many relations") + t.Errorf("Should be able to find many to many relations") } // db.Model(&User{}).Many2Many("Languages").Add(&Language{}) diff --git a/migration_test.go b/migration_test.go index 68982a78..607668ad 100644 --- a/migration_test.go +++ b/migration_test.go @@ -18,7 +18,7 @@ func runMigration() { db.Exec("drop table roles") db.Exec("drop table companies") db.Exec("drop table animals") - db.Exec("drop table user_companies") + db.Exec("drop table user_languages") if err := db.CreateTable(&Animal{}).Error; err != nil { panic(fmt.Sprintf("No error should happen when create table, but got %+v", err))