10 "github.com/jinzhu/gorm"
13 func TestBelongsTo(t *testing.T) {
15 Title: "post belongs to",
16 Body: "body belongs to",
17 Category: Category{Name: "Category 1"},
18 MainCategory: Category{Name: "Main Category 1"},
21 if err := DB.Save(&post).Error; err != nil {
22 t.Error("Got errors when save post", err)
25 if post.Category.ID == 0 || post.MainCategory.ID == 0 {
26 t.Errorf("Category's primary key should be updated")
29 if post.CategoryId.Int64 == 0 || post.MainCategoryId == 0 {
30 t.Errorf("post's foreign key should be updated")
34 var category1 Category
35 DB.Model(&post).Association("Category").Find(&category1)
36 if category1.Name != "Category 1" {
37 t.Errorf("Query belongs to relations with Association")
40 var mainCategory1 Category
41 DB.Model(&post).Association("MainCategory").Find(&mainCategory1)
42 if mainCategory1.Name != "Main Category 1" {
43 t.Errorf("Query belongs to relations with Association")
46 var category11 Category
47 DB.Model(&post).Related(&category11)
48 if category11.Name != "Category 1" {
49 t.Errorf("Query belongs to relations with Related")
52 if DB.Model(&post).Association("Category").Count() != 1 {
53 t.Errorf("Post's category count should be 1")
56 if DB.Model(&post).Association("MainCategory").Count() != 1 {
57 t.Errorf("Post's main category count should be 1")
61 var category2 = Category{
64 DB.Model(&post).Association("Category").Append(&category2)
66 if category2.ID == 0 {
67 t.Errorf("Category should has ID when created with Append")
70 var category21 Category
71 DB.Model(&post).Related(&category21)
73 if category21.Name != "Category 2" {
74 t.Errorf("Category should be updated with Append")
77 if DB.Model(&post).Association("Category").Count() != 1 {
78 t.Errorf("Post's category count should be 1")
82 var category3 = Category{
85 DB.Model(&post).Association("Category").Replace(&category3)
87 if category3.ID == 0 {
88 t.Errorf("Category should has ID when created with Replace")
91 var category31 Category
92 DB.Model(&post).Related(&category31)
93 if category31.Name != "Category 3" {
94 t.Errorf("Category should be updated with Replace")
97 if DB.Model(&post).Association("Category").Count() != 1 {
98 t.Errorf("Post's category count should be 1")
102 DB.Model(&post).Association("Category").Delete(&category2)
103 if DB.Model(&post).Related(&Category{}).RecordNotFound() {
104 t.Errorf("Should not delete any category when Delete a unrelated Category")
107 if post.Category.Name == "" {
108 t.Errorf("Post's category should not be reseted when Delete a unrelated Category")
111 DB.Model(&post).Association("Category").Delete(&category3)
113 if post.Category.Name != "" {
114 t.Errorf("Post's category should be reseted after Delete")
117 var category41 Category
118 DB.Model(&post).Related(&category41)
119 if category41.Name != "" {
120 t.Errorf("Category should be deleted with Delete")
123 if count := DB.Model(&post).Association("Category").Count(); count != 0 {
124 t.Errorf("Post's category count should be 0 after Delete, but got %v", count)
128 DB.Model(&post).Association("Category").Append(&Category{
132 if DB.Model(&post).Related(&Category{}).RecordNotFound() {
133 t.Errorf("Should find category after append")
136 if post.Category.Name == "" {
137 t.Errorf("Post's category should has value after Append")
140 DB.Model(&post).Association("Category").Clear()
142 if post.Category.Name != "" {
143 t.Errorf("Post's category should be cleared after Clear")
146 if !DB.Model(&post).Related(&Category{}).RecordNotFound() {
147 t.Errorf("Should not find any category after Clear")
150 if count := DB.Model(&post).Association("Category").Count(); count != 0 {
151 t.Errorf("Post's category count should be 0 after Clear, but got %v", count)
154 // Check Association mode with soft delete
155 category6 := Category{
158 DB.Model(&post).Association("Category").Append(&category6)
160 if count := DB.Model(&post).Association("Category").Count(); count != 1 {
161 t.Errorf("Post's category count should be 1 after Append, but got %v", count)
164 DB.Delete(&category6)
166 if count := DB.Model(&post).Association("Category").Count(); count != 0 {
167 t.Errorf("Post's category count should be 0 after the category has been deleted, but got %v", count)
170 if err := DB.Model(&post).Association("Category").Find(&Category{}).Error; err == nil {
171 t.Errorf("Post's category is not findable after Delete")
174 if count := DB.Unscoped().Model(&post).Association("Category").Count(); count != 1 {
175 t.Errorf("Post's category count should be 1 when query with Unscoped, but got %v", count)
178 if err := DB.Unscoped().Model(&post).Association("Category").Find(&Category{}).Error; err != nil {
179 t.Errorf("Post's category should be findable when query with Unscoped, got %v", err)
183 func TestBelongsToOverrideForeignKey1(t *testing.T) {
184 type Profile struct {
191 Profile Profile `gorm:"ForeignKey:ProfileRefer"`
195 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {
196 if relation.Relationship.Kind != "belongs_to" ||
197 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"ProfileRefer"}) ||
198 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) {
199 t.Errorf("Override belongs to foreign key with tag")
204 func TestBelongsToOverrideForeignKey2(t *testing.T) {
205 type Profile struct {
213 Profile Profile `gorm:"ForeignKey:ProfileID;AssociationForeignKey:Refer"`
217 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {
218 if relation.Relationship.Kind != "belongs_to" ||
219 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"ProfileID"}) ||
220 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) {
221 t.Errorf("Override belongs to foreign key with tag")
226 func TestHasOne(t *testing.T) {
229 CreditCard: CreditCard{Number: "411111111111"},
232 if err := DB.Save(&user).Error; err != nil {
233 t.Error("Got errors when save user", err.Error())
236 if user.CreditCard.UserId.Int64 == 0 {
237 t.Errorf("CreditCard's foreign key should be updated")
241 var creditCard1 CreditCard
242 DB.Model(&user).Related(&creditCard1)
244 if creditCard1.Number != "411111111111" {
245 t.Errorf("Query has one relations with Related")
248 var creditCard11 CreditCard
249 DB.Model(&user).Association("CreditCard").Find(&creditCard11)
251 if creditCard11.Number != "411111111111" {
252 t.Errorf("Query has one relations with Related")
255 if DB.Model(&user).Association("CreditCard").Count() != 1 {
256 t.Errorf("User's credit card count should be 1")
260 var creditcard2 = CreditCard{
261 Number: "411111111112",
263 DB.Model(&user).Association("CreditCard").Append(&creditcard2)
265 if creditcard2.ID == 0 {
266 t.Errorf("Creditcard should has ID when created with Append")
269 var creditcard21 CreditCard
270 DB.Model(&user).Related(&creditcard21)
271 if creditcard21.Number != "411111111112" {
272 t.Errorf("CreditCard should be updated with Append")
275 if DB.Model(&user).Association("CreditCard").Count() != 1 {
276 t.Errorf("User's credit card count should be 1")
280 var creditcard3 = CreditCard{
281 Number: "411111111113",
283 DB.Model(&user).Association("CreditCard").Replace(&creditcard3)
285 if creditcard3.ID == 0 {
286 t.Errorf("Creditcard should has ID when created with Replace")
289 var creditcard31 CreditCard
290 DB.Model(&user).Related(&creditcard31)
291 if creditcard31.Number != "411111111113" {
292 t.Errorf("CreditCard should be updated with Replace")
295 if DB.Model(&user).Association("CreditCard").Count() != 1 {
296 t.Errorf("User's credit card count should be 1")
300 DB.Model(&user).Association("CreditCard").Delete(&creditcard2)
301 var creditcard4 CreditCard
302 DB.Model(&user).Related(&creditcard4)
303 if creditcard4.Number != "411111111113" {
304 t.Errorf("Should not delete credit card when Delete a unrelated CreditCard")
307 if DB.Model(&user).Association("CreditCard").Count() != 1 {
308 t.Errorf("User's credit card count should be 1")
311 DB.Model(&user).Association("CreditCard").Delete(&creditcard3)
312 if !DB.Model(&user).Related(&CreditCard{}).RecordNotFound() {
313 t.Errorf("Should delete credit card with Delete")
316 if DB.Model(&user).Association("CreditCard").Count() != 0 {
317 t.Errorf("User's credit card count should be 0 after Delete")
321 var creditcard5 = CreditCard{
322 Number: "411111111115",
324 DB.Model(&user).Association("CreditCard").Append(&creditcard5)
326 if DB.Model(&user).Related(&CreditCard{}).RecordNotFound() {
327 t.Errorf("Should added credit card with Append")
330 if DB.Model(&user).Association("CreditCard").Count() != 1 {
331 t.Errorf("User's credit card count should be 1")
334 DB.Model(&user).Association("CreditCard").Clear()
335 if !DB.Model(&user).Related(&CreditCard{}).RecordNotFound() {
336 t.Errorf("Credit card should be deleted with Clear")
339 if DB.Model(&user).Association("CreditCard").Count() != 0 {
340 t.Errorf("User's credit card count should be 0 after Clear")
343 // Check Association mode with soft delete
344 var creditcard6 = CreditCard{
345 Number: "411111111116",
347 DB.Model(&user).Association("CreditCard").Append(&creditcard6)
349 if count := DB.Model(&user).Association("CreditCard").Count(); count != 1 {
350 t.Errorf("User's credit card count should be 1 after Append, but got %v", count)
353 DB.Delete(&creditcard6)
355 if count := DB.Model(&user).Association("CreditCard").Count(); count != 0 {
356 t.Errorf("User's credit card count should be 0 after credit card deleted, but got %v", count)
359 if err := DB.Model(&user).Association("CreditCard").Find(&CreditCard{}).Error; err == nil {
360 t.Errorf("User's creditcard is not findable after Delete")
363 if count := DB.Unscoped().Model(&user).Association("CreditCard").Count(); count != 1 {
364 t.Errorf("User's credit card count should be 1 when query with Unscoped, but got %v", count)
367 if err := DB.Unscoped().Model(&user).Association("CreditCard").Find(&CreditCard{}).Error; err != nil {
368 t.Errorf("User's creditcard should be findable when query with Unscoped, got %v", err)
372 func TestHasOneOverrideForeignKey1(t *testing.T) {
373 type Profile struct {
381 Profile Profile `gorm:"ForeignKey:UserRefer"`
384 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {
385 if relation.Relationship.Kind != "has_one" ||
386 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserRefer"}) ||
387 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) {
388 t.Errorf("Override belongs to foreign key with tag")
393 func TestHasOneOverrideForeignKey2(t *testing.T) {
394 type Profile struct {
403 Profile Profile `gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"`
406 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {
407 if relation.Relationship.Kind != "has_one" ||
408 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserID"}) ||
409 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) {
410 t.Errorf("Override belongs to foreign key with tag")
415 func TestHasMany(t *testing.T) {
417 Title: "post has many",
418 Body: "body has many",
419 Comments: []*Comment{{Content: "Comment 1"}, {Content: "Comment 2"}},
422 if err := DB.Save(&post).Error; err != nil {
423 t.Error("Got errors when save post", err)
426 for _, comment := range post.Comments {
427 if comment.PostId == 0 {
428 t.Errorf("comment's PostID should be updated")
432 var compareComments = func(comments []Comment, contents []string) bool {
433 var commentContents []string
434 for _, comment := range comments {
435 commentContents = append(commentContents, comment.Content)
437 sort.Strings(commentContents)
438 sort.Strings(contents)
439 return reflect.DeepEqual(commentContents, contents)
443 if DB.First(&Comment{}, "content = ?", "Comment 1").Error != nil {
444 t.Errorf("Comment 1 should be saved")
447 var comments1 []Comment
448 DB.Model(&post).Association("Comments").Find(&comments1)
449 if !compareComments(comments1, []string{"Comment 1", "Comment 2"}) {
450 t.Errorf("Query has many relations with Association")
453 var comments11 []Comment
454 DB.Model(&post).Related(&comments11)
455 if !compareComments(comments11, []string{"Comment 1", "Comment 2"}) {
456 t.Errorf("Query has many relations with Related")
459 if DB.Model(&post).Association("Comments").Count() != 2 {
460 t.Errorf("Post's comments count should be 2")
464 DB.Model(&post).Association("Comments").Append(&Comment{Content: "Comment 3"})
466 var comments2 []Comment
467 DB.Model(&post).Related(&comments2)
468 if !compareComments(comments2, []string{"Comment 1", "Comment 2", "Comment 3"}) {
469 t.Errorf("Append new record to has many relations")
472 if DB.Model(&post).Association("Comments").Count() != 3 {
473 t.Errorf("Post's comments count should be 3 after Append")
477 DB.Model(&post).Association("Comments").Delete(comments11)
479 var comments3 []Comment
480 DB.Model(&post).Related(&comments3)
481 if !compareComments(comments3, []string{"Comment 3"}) {
482 t.Errorf("Delete an existing resource for has many relations")
485 if DB.Model(&post).Association("Comments").Count() != 1 {
486 t.Errorf("Post's comments count should be 1 after Delete 2")
490 DB.Model(&Post{Id: 999}).Association("Comments").Replace()
492 var comments4 []Comment
493 DB.Model(&post).Related(&comments4)
494 if len(comments4) == 0 {
495 t.Errorf("Replace for other resource should not clear all comments")
498 DB.Model(&post).Association("Comments").Replace(&Comment{Content: "Comment 4"}, &Comment{Content: "Comment 5"})
500 var comments41 []Comment
501 DB.Model(&post).Related(&comments41)
502 if !compareComments(comments41, []string{"Comment 4", "Comment 5"}) {
503 t.Errorf("Replace has many relations")
507 DB.Model(&Post{Id: 999}).Association("Comments").Clear()
509 var comments5 []Comment
510 DB.Model(&post).Related(&comments5)
511 if len(comments5) == 0 {
512 t.Errorf("Clear should not clear all comments")
515 DB.Model(&post).Association("Comments").Clear()
517 var comments51 []Comment
518 DB.Model(&post).Related(&comments51)
519 if len(comments51) != 0 {
520 t.Errorf("Clear has many relations")
523 // Check Association mode with soft delete
524 var comment6 = Comment{
525 Content: "comment 6",
527 DB.Model(&post).Association("Comments").Append(&comment6)
529 if count := DB.Model(&post).Association("Comments").Count(); count != 1 {
530 t.Errorf("post's comments count should be 1 after Append, but got %v", count)
535 if count := DB.Model(&post).Association("Comments").Count(); count != 0 {
536 t.Errorf("post's comments count should be 0 after comment been deleted, but got %v", count)
539 var comments6 []Comment
540 if DB.Model(&post).Association("Comments").Find(&comments6); len(comments6) != 0 {
541 t.Errorf("post's comments count should be 0 when find with Find, but got %v", len(comments6))
544 if count := DB.Unscoped().Model(&post).Association("Comments").Count(); count != 1 {
545 t.Errorf("post's comments count should be 1 when query with Unscoped, but got %v", count)
548 var comments61 []Comment
549 if DB.Unscoped().Model(&post).Association("Comments").Find(&comments61); len(comments61) != 1 {
550 t.Errorf("post's comments count should be 1 when query with Unscoped, but got %v", len(comments61))
554 func TestHasManyOverrideForeignKey1(t *testing.T) {
555 type Profile struct {
563 Profile []Profile `gorm:"ForeignKey:UserRefer"`
566 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {
567 if relation.Relationship.Kind != "has_many" ||
568 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserRefer"}) ||
569 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"ID"}) {
570 t.Errorf("Override belongs to foreign key with tag")
575 func TestHasManyOverrideForeignKey2(t *testing.T) {
576 type Profile struct {
585 Profile []Profile `gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"`
588 if relation, ok := DB.NewScope(&User{}).FieldByName("Profile"); ok {
589 if relation.Relationship.Kind != "has_many" ||
590 !reflect.DeepEqual(relation.Relationship.ForeignFieldNames, []string{"UserID"}) ||
591 !reflect.DeepEqual(relation.Relationship.AssociationForeignFieldNames, []string{"Refer"}) {
592 t.Errorf("Override belongs to foreign key with tag")
597 func TestManyToMany(t *testing.T) {
598 DB.Raw("delete from languages")
599 var languages = []Language{{Name: "ZH"}, {Name: "EN"}}
600 user := User{Name: "Many2Many", Languages: languages}
604 var newLanguages []Language
605 DB.Model(&user).Related(&newLanguages, "Languages")
606 if len(newLanguages) != len([]string{"ZH", "EN"}) {
607 t.Errorf("Query many to many relations")
610 DB.Model(&user).Association("Languages").Find(&newLanguages)
611 if len(newLanguages) != len([]string{"ZH", "EN"}) {
612 t.Errorf("Should be able to find many to many relations")
615 if DB.Model(&user).Association("Languages").Count() != len([]string{"ZH", "EN"}) {
616 t.Errorf("Count should return correct result")
620 DB.Model(&user).Association("Languages").Append(&Language{Name: "DE"})
621 if DB.Where("name = ?", "DE").First(&Language{}).RecordNotFound() {
622 t.Errorf("New record should be saved when append")
625 languageA := Language{Name: "AA"}
627 DB.Model(&User{Id: user.Id}).Association("Languages").Append(&languageA)
629 languageC := Language{Name: "CC"}
631 DB.Model(&user).Association("Languages").Append(&[]Language{{Name: "BB"}, languageC})
633 DB.Model(&User{Id: user.Id}).Association("Languages").Append(&[]Language{{Name: "DD"}, {Name: "EE"}})
635 totalLanguages := []string{"ZH", "EN", "DE", "AA", "BB", "CC", "DD", "EE"}
637 if DB.Model(&user).Association("Languages").Count() != len(totalLanguages) {
638 t.Errorf("All appended languages should be saved")
642 user.Languages = []Language{}
643 DB.Model(&user).Association("Languages").Find(&user.Languages)
645 var language Language
646 DB.Where("name = ?", "EE").First(&language)
647 DB.Model(&user).Association("Languages").Delete(language, &language)
649 if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-1 || len(user.Languages) != len(totalLanguages)-1 {
650 t.Errorf("Relations should be deleted with Delete")
652 if DB.Where("name = ?", "EE").First(&Language{}).RecordNotFound() {
653 t.Errorf("Language EE should not be deleted")
656 DB.Where("name IN (?)", []string{"CC", "DD"}).Find(&languages)
658 user2 := User{Name: "Many2Many_User2", Languages: languages}
661 DB.Model(&user).Association("Languages").Delete(languages, &languages)
662 if DB.Model(&user).Association("Languages").Count() != len(totalLanguages)-3 || len(user.Languages) != len(totalLanguages)-3 {
663 t.Errorf("Relations should be deleted with Delete")
666 if DB.Model(&user2).Association("Languages").Count() == 0 {
667 t.Errorf("Other user's relations should not be deleted")
671 var languageB Language
672 DB.Where("name = ?", "BB").First(&languageB)
673 DB.Model(&user).Association("Languages").Replace(languageB)
674 if len(user.Languages) != 1 || DB.Model(&user).Association("Languages").Count() != 1 {
675 t.Errorf("Relations should be replaced")
678 DB.Model(&user).Association("Languages").Replace()
679 if len(user.Languages) != 0 || DB.Model(&user).Association("Languages").Count() != 0 {
680 t.Errorf("Relations should be replaced with empty")
683 DB.Model(&user).Association("Languages").Replace(&[]Language{{Name: "FF"}, {Name: "JJ"}})
684 if len(user.Languages) != 2 || DB.Model(&user).Association("Languages").Count() != len([]string{"FF", "JJ"}) {
685 t.Errorf("Relations should be replaced")
689 DB.Model(&user).Association("Languages").Clear()
690 if len(user.Languages) != 0 || DB.Model(&user).Association("Languages").Count() != 0 {
691 t.Errorf("Relations should be cleared")
694 // Check Association mode with soft delete
695 var language6 = Language{
698 DB.Model(&user).Association("Languages").Append(&language6)
700 if count := DB.Model(&user).Association("Languages").Count(); count != 1 {
701 t.Errorf("user's languages count should be 1 after Append, but got %v", count)
704 DB.Delete(&language6)
706 if count := DB.Model(&user).Association("Languages").Count(); count != 0 {
707 t.Errorf("user's languages count should be 0 after language been deleted, but got %v", count)
710 var languages6 []Language
711 if DB.Model(&user).Association("Languages").Find(&languages6); len(languages6) != 0 {
712 t.Errorf("user's languages count should be 0 when find with Find, but got %v", len(languages6))
715 if count := DB.Unscoped().Model(&user).Association("Languages").Count(); count != 1 {
716 t.Errorf("user's languages count should be 1 when query with Unscoped, but got %v", count)
719 var languages61 []Language
720 if DB.Unscoped().Model(&user).Association("Languages").Find(&languages61); len(languages61) != 1 {
721 t.Errorf("user's languages count should be 1 when query with Unscoped, but got %v", len(languages61))
725 func TestRelated(t *testing.T) {
728 BillingAddress: Address{Address1: "Billing Address - Address 1"},
729 ShippingAddress: Address{Address1: "Shipping Address - Address 1"},
730 Emails: []Email{{Email: "jinzhu@example.com"}, {Email: "jinzhu-2@example@example.com"}},
731 CreditCard: CreditCard{Number: "1234567890"},
732 Company: Company{Name: "company1"},
735 if err := DB.Save(&user).Error; err != nil {
736 t.Errorf("No error should happen when saving user")
739 if user.CreditCard.ID == 0 {
740 t.Errorf("After user save, credit card should have id")
743 if user.BillingAddress.ID == 0 {
744 t.Errorf("After user save, billing address should have id")
747 if user.Emails[0].Id == 0 {
748 t.Errorf("After user save, billing address should have id")
752 DB.Model(&user).Related(&emails)
753 if len(emails) != 2 {
754 t.Errorf("Should have two emails")
758 DB.Model(&user).Where("email = ?", "jinzhu@example.com").Related(&emails2)
759 if len(emails2) != 1 {
760 t.Errorf("Should have two emails")
764 DB.Model(&user).Related(&emails3)
765 if len(emails3) != 2 {
766 t.Errorf("Should have two emails")
770 DB.Model(&user).Related(&user1.Emails)
771 if len(user1.Emails) != 2 {
772 t.Errorf("Should have only one email match related condition")
776 DB.Model(&user).Related(&address1, "BillingAddressId")
777 if address1.Address1 != "Billing Address - Address 1" {
778 t.Errorf("Should get billing address from user correctly")
782 DB.Model(&address1).Related(&user1, "BillingAddressId")
783 if DB.NewRecord(user1) {
784 t.Errorf("Should get user from address correctly")
788 DB.Model(&emails[0]).Related(&user2)
789 if user2.Id != user.Id || user2.Name != user.Name {
790 t.Errorf("Should get user from email correctly")
793 var creditcard CreditCard
795 DB.First(&creditcard, "number = ?", "1234567890")
796 DB.Model(&creditcard).Related(&user3)
797 if user3.Id != user.Id || user3.Name != user.Name {
798 t.Errorf("Should get user from credit card correctly")
801 if !DB.Model(&CreditCard{}).Related(&User{}).RecordNotFound() {
802 t.Errorf("RecordNotFound for Related")
806 if DB.Model(&user).Related(&company, "Company").RecordNotFound() || company.Name != "company1" {
807 t.Errorf("RecordNotFound for Related")
811 func TestForeignKey(t *testing.T) {
812 for _, structField := range DB.NewScope(&User{}).GetStructFields() {
813 for _, foreignKey := range []string{"BillingAddressID", "ShippingAddressId", "CompanyID"} {
814 if structField.Name == foreignKey && !structField.IsForeignKey {
815 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))
820 for _, structField := range DB.NewScope(&Email{}).GetStructFields() {
821 for _, foreignKey := range []string{"UserId"} {
822 if structField.Name == foreignKey && !structField.IsForeignKey {
823 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))
828 for _, structField := range DB.NewScope(&Post{}).GetStructFields() {
829 for _, foreignKey := range []string{"CategoryId", "MainCategoryId"} {
830 if structField.Name == foreignKey && !structField.IsForeignKey {
831 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))
836 for _, structField := range DB.NewScope(&Comment{}).GetStructFields() {
837 for _, foreignKey := range []string{"PostId"} {
838 if structField.Name == foreignKey && !structField.IsForeignKey {
839 t.Errorf(fmt.Sprintf("%v should be foreign key", foreignKey))
845 func testForeignKey(t *testing.T, source interface{}, sourceFieldName string, target interface{}, targetFieldName string) {
846 if dialect := os.Getenv("GORM_DIALECT"); dialect == "" || dialect == "sqlite" {
847 // sqlite does not support ADD CONSTRAINT in ALTER TABLE
850 targetScope := DB.NewScope(target)
851 targetTableName := targetScope.TableName()
852 modelScope := DB.NewScope(source)
853 modelField, ok := modelScope.FieldByName(sourceFieldName)
855 t.Fatalf(fmt.Sprintf("Failed to get field by name: %v", sourceFieldName))
857 targetField, ok := targetScope.FieldByName(targetFieldName)
859 t.Fatalf(fmt.Sprintf("Failed to get field by name: %v", targetFieldName))
861 dest := fmt.Sprintf("%v(%v)", targetTableName, targetField.DBName)
862 err := DB.Model(source).AddForeignKey(modelField.DBName, dest, "CASCADE", "CASCADE").Error
864 t.Fatalf(fmt.Sprintf("Failed to create foreign key: %v", err))
868 func TestLongForeignKey(t *testing.T) {
869 testForeignKey(t, &NotSoLongTableName{}, "ReallyLongThingID", &ReallyLongTableNameToTestMySQLNameLengthLimit{}, "ID")
872 func TestLongForeignKeyWithShortDest(t *testing.T) {
873 testForeignKey(t, &ReallyLongThingThatReferencesShort{}, "ShortID", &Short{}, "ID")
876 func TestHasManyChildrenWithOneStruct(t *testing.T) {
877 category := Category{
879 Categories: []Category{
888 func TestAutoSaveBelongsToAssociation(t *testing.T) {
889 type Company struct {
898 Company Company `gorm:"association_autoupdate:false;association_autocreate:false;"`
901 DB.Where("name = ?", "auto_save_association").Delete(&Company{})
902 DB.AutoMigrate(&Company{}, &User{})
904 DB.Save(&User{Name: "jinzhu", Company: Company{Name: "auto_save_association"}})
906 if !DB.Where("name = ?", "auto_save_association").First(&Company{}).RecordNotFound() {
907 t.Errorf("Company auto_save_association should not have been saved when autosave is false")
910 // if foreign key is set, this should be saved even if association isn't
911 company := Company{Name: "auto_save_association"}
914 company.Name = "auto_save_association_new_name"
915 user := User{Name: "jinzhu", Company: company}
919 if !DB.Where("name = ?", "auto_save_association_new_name").First(&Company{}).RecordNotFound() {
920 t.Errorf("Company should not have been updated")
923 if DB.Where("id = ? AND company_id = ?", user.ID, company.ID).First(&User{}).RecordNotFound() {
924 t.Errorf("User's foreign key should have been saved")
927 user2 := User{Name: "jinzhu_2", Company: Company{Name: "auto_save_association_2"}}
928 DB.Set("gorm:association_autocreate", true).Save(&user2)
929 if DB.Where("name = ?", "auto_save_association_2").First(&Company{}).RecordNotFound() {
930 t.Errorf("Company auto_save_association_2 should been created when autocreate is true")
933 user2.Company.Name = "auto_save_association_2_newname"
934 DB.Set("gorm:association_autoupdate", true).Save(&user2)
936 if DB.Where("name = ?", "auto_save_association_2_newname").First(&Company{}).RecordNotFound() {
937 t.Errorf("Company should been updated")
941 func TestAutoSaveHasOneAssociation(t *testing.T) {
942 type Company struct {
951 Company Company `gorm:"association_autoupdate:false;association_autocreate:false;"`
954 DB.Where("name = ?", "auto_save_has_one_association").Delete(&Company{})
955 DB.AutoMigrate(&Company{}, &User{})
957 DB.Save(&User{Name: "jinzhu", Company: Company{Name: "auto_save_has_one_association"}})
959 if !DB.Where("name = ?", "auto_save_has_one_association").First(&Company{}).RecordNotFound() {
960 t.Errorf("Company auto_save_has_one_association should not have been saved when autosave is false")
963 company := Company{Name: "auto_save_has_one_association"}
966 company.Name = "auto_save_has_one_association_new_name"
967 user := User{Name: "jinzhu", Company: company}
971 if !DB.Where("name = ?", "auto_save_has_one_association_new_name").First(&Company{}).RecordNotFound() {
972 t.Errorf("Company should not have been updated")
975 if !DB.Where("name = ? AND user_id = ?", "auto_save_has_one_association", user.ID).First(&Company{}).RecordNotFound() {
976 t.Errorf("Company should not have been updated")
979 if user.Company.UserID == 0 {
980 t.Errorf("UserID should be assigned")
983 company.Name = "auto_save_has_one_association_2_new_name"
984 DB.Set("gorm:association_autoupdate", true).Save(&user)
986 if DB.Where("name = ? AND user_id = ?", "auto_save_has_one_association_new_name", user.ID).First(&Company{}).RecordNotFound() {
987 t.Errorf("Company should been updated")
990 user2 := User{Name: "jinzhu_2", Company: Company{Name: "auto_save_has_one_association_2"}}
991 DB.Set("gorm:association_autocreate", true).Save(&user2)
992 if DB.Where("name = ?", "auto_save_has_one_association_2").First(&Company{}).RecordNotFound() {
993 t.Errorf("Company auto_save_has_one_association_2 should been created when autocreate is true")
997 func TestAutoSaveMany2ManyAssociation(t *testing.T) {
998 type Company struct {
1006 Companies []Company `gorm:"many2many:user_companies;association_autoupdate:false;association_autocreate:false;"`
1009 DB.AutoMigrate(&Company{}, &User{})
1011 DB.Save(&User{Name: "jinzhu", Companies: []Company{{Name: "auto_save_m2m_association"}}})
1013 if !DB.Where("name = ?", "auto_save_m2m_association").First(&Company{}).RecordNotFound() {
1014 t.Errorf("Company auto_save_m2m_association should not have been saved when autosave is false")
1017 company := Company{Name: "auto_save_m2m_association"}
1020 company.Name = "auto_save_m2m_association_new_name"
1021 user := User{Name: "jinzhu", Companies: []Company{company, {Name: "auto_save_m2m_association_new_name_2"}}}
1025 if !DB.Where("name = ?", "auto_save_m2m_association_new_name").First(&Company{}).RecordNotFound() {
1026 t.Errorf("Company should not have been updated")
1029 if !DB.Where("name = ?", "auto_save_m2m_association_new_name_2").First(&Company{}).RecordNotFound() {
1030 t.Errorf("Company should not been created")
1033 if DB.Model(&user).Association("Companies").Count() != 1 {
1034 t.Errorf("Relationship should been saved")
1037 DB.Set("gorm:association_autoupdate", true).Set("gorm:association_autocreate", true).Save(&user)
1039 if DB.Where("name = ?", "auto_save_m2m_association_new_name").First(&Company{}).RecordNotFound() {
1040 t.Errorf("Company should been updated")
1043 if DB.Where("name = ?", "auto_save_m2m_association_new_name_2").First(&Company{}).RecordNotFound() {
1044 t.Errorf("Company should been created")
1047 if DB.Model(&user).Association("Companies").Count() != 2 {
1048 t.Errorf("Relationship should been updated")