11 ID uint `gorm:"primary_key"`
12 Locale string `gorm:"primary_key"`
15 Tags []Tag `gorm:"many2many:blog_tags;"`
16 SharedTags []Tag `gorm:"many2many:shared_blog_tags;ForeignKey:id;AssociationForeignKey:id"`
17 LocaleTags []Tag `gorm:"many2many:locale_blog_tags;ForeignKey:id,locale;AssociationForeignKey:id"`
21 ID uint `gorm:"primary_key"`
22 Locale string `gorm:"primary_key"`
24 Blogs []*Blog `gorm:"many2many:blogs_tags"`
27 func compareTags(tags []Tag, contents []string) bool {
28 var tagContents []string
29 for _, tag := range tags {
30 tagContents = append(tagContents, tag.Value)
32 sort.Strings(tagContents)
33 sort.Strings(contents)
34 return reflect.DeepEqual(tagContents, contents)
37 func TestManyToManyWithMultiPrimaryKeys(t *testing.T) {
38 if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" {
39 DB.DropTable(&Blog{}, &Tag{})
40 DB.DropTable("blog_tags")
41 DB.CreateTable(&Blog{}, &Tag{})
47 {Locale: "ZH", Value: "tag1"},
48 {Locale: "ZH", Value: "tag2"},
53 if !compareTags(blog.Tags, []string{"tag1", "tag2"}) {
54 t.Errorf("Blog should has two tags")
58 var tag3 = &Tag{Locale: "ZH", Value: "tag3"}
59 DB.Model(&blog).Association("Tags").Append([]*Tag{tag3})
60 if !compareTags(blog.Tags, []string{"tag1", "tag2", "tag3"}) {
61 t.Errorf("Blog should has three tags after Append")
64 if DB.Model(&blog).Association("Tags").Count() != 3 {
65 t.Errorf("Blog should has three tags after Append")
69 DB.Model(&blog).Related(&tags, "Tags")
70 if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
71 t.Errorf("Should find 3 tags with Related")
75 DB.Preload("Tags").Find(&blog1)
76 if !compareTags(blog1.Tags, []string{"tag1", "tag2", "tag3"}) {
77 t.Errorf("Preload many2many relations")
81 var tag5 = &Tag{Locale: "ZH", Value: "tag5"}
82 var tag6 = &Tag{Locale: "ZH", Value: "tag6"}
83 DB.Model(&blog).Association("Tags").Replace(tag5, tag6)
85 DB.Model(&blog).Related(&tags2, "Tags")
86 if !compareTags(tags2, []string{"tag5", "tag6"}) {
87 t.Errorf("Should find 2 tags after Replace")
90 if DB.Model(&blog).Association("Tags").Count() != 2 {
91 t.Errorf("Blog should has three tags after Replace")
95 DB.Model(&blog).Association("Tags").Delete(tag5)
97 DB.Model(&blog).Related(&tags3, "Tags")
98 if !compareTags(tags3, []string{"tag6"}) {
99 t.Errorf("Should find 1 tags after Delete")
102 if DB.Model(&blog).Association("Tags").Count() != 1 {
103 t.Errorf("Blog should has three tags after Delete")
106 DB.Model(&blog).Association("Tags").Delete(tag3)
108 DB.Model(&blog).Related(&tags4, "Tags")
109 if !compareTags(tags4, []string{"tag6"}) {
110 t.Errorf("Tag should not be deleted when Delete with a unrelated tag")
114 DB.Model(&blog).Association("Tags").Clear()
115 if DB.Model(&blog).Association("Tags").Count() != 0 {
116 t.Errorf("All tags should be cleared")
121 func TestManyToManyWithCustomizedForeignKeys(t *testing.T) {
122 if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" {
123 DB.DropTable(&Blog{}, &Tag{})
124 DB.DropTable("shared_blog_tags")
125 DB.CreateTable(&Blog{}, &Tag{})
131 {Locale: "ZH", Value: "tag1"},
132 {Locale: "ZH", Value: "tag2"},
143 if !compareTags(blog.SharedTags, []string{"tag1", "tag2"}) {
144 t.Errorf("Blog should has two tags")
148 var tag3 = &Tag{Locale: "ZH", Value: "tag3"}
149 DB.Model(&blog).Association("SharedTags").Append([]*Tag{tag3})
150 if !compareTags(blog.SharedTags, []string{"tag1", "tag2", "tag3"}) {
151 t.Errorf("Blog should has three tags after Append")
154 if DB.Model(&blog).Association("SharedTags").Count() != 3 {
155 t.Errorf("Blog should has three tags after Append")
158 if DB.Model(&blog2).Association("SharedTags").Count() != 3 {
159 t.Errorf("Blog should has three tags after Append")
163 DB.Model(&blog).Related(&tags, "SharedTags")
164 if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
165 t.Errorf("Should find 3 tags with Related")
168 DB.Model(&blog2).Related(&tags, "SharedTags")
169 if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
170 t.Errorf("Should find 3 tags with Related")
174 DB.Preload("SharedTags").Find(&blog1)
175 if !compareTags(blog1.SharedTags, []string{"tag1", "tag2", "tag3"}) {
176 t.Errorf("Preload many2many relations")
179 var tag4 = &Tag{Locale: "ZH", Value: "tag4"}
180 DB.Model(&blog2).Association("SharedTags").Append(tag4)
182 DB.Model(&blog).Related(&tags, "SharedTags")
183 if !compareTags(tags, []string{"tag1", "tag2", "tag3", "tag4"}) {
184 t.Errorf("Should find 3 tags with Related")
187 DB.Model(&blog2).Related(&tags, "SharedTags")
188 if !compareTags(tags, []string{"tag1", "tag2", "tag3", "tag4"}) {
189 t.Errorf("Should find 3 tags with Related")
193 var tag5 = &Tag{Locale: "ZH", Value: "tag5"}
194 var tag6 = &Tag{Locale: "ZH", Value: "tag6"}
195 DB.Model(&blog2).Association("SharedTags").Replace(tag5, tag6)
197 DB.Model(&blog).Related(&tags2, "SharedTags")
198 if !compareTags(tags2, []string{"tag5", "tag6"}) {
199 t.Errorf("Should find 2 tags after Replace")
202 DB.Model(&blog2).Related(&tags2, "SharedTags")
203 if !compareTags(tags2, []string{"tag5", "tag6"}) {
204 t.Errorf("Should find 2 tags after Replace")
207 if DB.Model(&blog).Association("SharedTags").Count() != 2 {
208 t.Errorf("Blog should has three tags after Replace")
212 DB.Model(&blog).Association("SharedTags").Delete(tag5)
214 DB.Model(&blog).Related(&tags3, "SharedTags")
215 if !compareTags(tags3, []string{"tag6"}) {
216 t.Errorf("Should find 1 tags after Delete")
219 if DB.Model(&blog).Association("SharedTags").Count() != 1 {
220 t.Errorf("Blog should has three tags after Delete")
223 DB.Model(&blog2).Association("SharedTags").Delete(tag3)
225 DB.Model(&blog).Related(&tags4, "SharedTags")
226 if !compareTags(tags4, []string{"tag6"}) {
227 t.Errorf("Tag should not be deleted when Delete with a unrelated tag")
231 DB.Model(&blog2).Association("SharedTags").Clear()
232 if DB.Model(&blog).Association("SharedTags").Count() != 0 {
233 t.Errorf("All tags should be cleared")
238 func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) {
239 if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" {
240 DB.DropTable(&Blog{}, &Tag{})
241 DB.DropTable("locale_blog_tags")
242 DB.CreateTable(&Blog{}, &Tag{})
248 {Locale: "ZH", Value: "tag1"},
249 {Locale: "ZH", Value: "tag2"},
261 var tag3 = &Tag{Locale: "ZH", Value: "tag3"}
262 DB.Model(&blog).Association("LocaleTags").Append([]*Tag{tag3})
263 if !compareTags(blog.LocaleTags, []string{"tag1", "tag2", "tag3"}) {
264 t.Errorf("Blog should has three tags after Append")
267 if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
268 t.Errorf("Blog should has three tags after Append")
271 if DB.Model(&blog2).Association("LocaleTags").Count() != 0 {
272 t.Errorf("EN Blog should has 0 tags after ZH Blog Append")
276 DB.Model(&blog).Related(&tags, "LocaleTags")
277 if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
278 t.Errorf("Should find 3 tags with Related")
281 DB.Model(&blog2).Related(&tags, "LocaleTags")
283 t.Errorf("Should find 0 tags with Related for EN Blog")
287 DB.Preload("LocaleTags").Find(&blog1, "locale = ? AND id = ?", "ZH", blog.ID)
288 if !compareTags(blog1.LocaleTags, []string{"tag1", "tag2", "tag3"}) {
289 t.Errorf("Preload many2many relations")
292 var tag4 = &Tag{Locale: "ZH", Value: "tag4"}
293 DB.Model(&blog2).Association("LocaleTags").Append(tag4)
295 DB.Model(&blog).Related(&tags, "LocaleTags")
296 if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
297 t.Errorf("Should find 3 tags with Related for EN Blog")
300 DB.Model(&blog2).Related(&tags, "LocaleTags")
301 if !compareTags(tags, []string{"tag4"}) {
302 t.Errorf("Should find 1 tags with Related for EN Blog")
306 var tag5 = &Tag{Locale: "ZH", Value: "tag5"}
307 var tag6 = &Tag{Locale: "ZH", Value: "tag6"}
308 DB.Model(&blog2).Association("LocaleTags").Replace(tag5, tag6)
311 DB.Model(&blog).Related(&tags2, "LocaleTags")
312 if !compareTags(tags2, []string{"tag1", "tag2", "tag3"}) {
313 t.Errorf("CN Blog's tags should not be changed after EN Blog Replace")
317 DB.Preload("LocaleTags").First(&blog11, "id = ? AND locale = ?", blog.ID, blog.Locale)
318 if !compareTags(blog11.LocaleTags, []string{"tag1", "tag2", "tag3"}) {
319 t.Errorf("CN Blog's tags should not be changed after EN Blog Replace")
322 DB.Model(&blog2).Related(&tags2, "LocaleTags")
323 if !compareTags(tags2, []string{"tag5", "tag6"}) {
324 t.Errorf("Should find 2 tags after Replace")
328 DB.Preload("LocaleTags").First(&blog21, "id = ? AND locale = ?", blog2.ID, blog2.Locale)
329 if !compareTags(blog21.LocaleTags, []string{"tag5", "tag6"}) {
330 t.Errorf("EN Blog's tags should be changed after Replace")
333 if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
334 t.Errorf("ZH Blog should has three tags after Replace")
337 if DB.Model(&blog2).Association("LocaleTags").Count() != 2 {
338 t.Errorf("EN Blog should has two tags after Replace")
342 DB.Model(&blog).Association("LocaleTags").Delete(tag5)
344 if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
345 t.Errorf("ZH Blog should has three tags after Delete with EN's tag")
348 if DB.Model(&blog2).Association("LocaleTags").Count() != 2 {
349 t.Errorf("EN Blog should has two tags after ZH Blog Delete with EN's tag")
352 DB.Model(&blog2).Association("LocaleTags").Delete(tag5)
354 if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
355 t.Errorf("ZH Blog should has three tags after EN Blog Delete with EN's tag")
358 if DB.Model(&blog2).Association("LocaleTags").Count() != 1 {
359 t.Errorf("EN Blog should has 1 tags after EN Blog Delete with EN's tag")
363 DB.Model(&blog2).Association("LocaleTags").Clear()
364 if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
365 t.Errorf("ZH Blog's tags should not be cleared when clear EN Blog's tags")
368 if DB.Model(&blog2).Association("LocaleTags").Count() != 0 {
369 t.Errorf("EN Blog's tags should be cleared when clear EN Blog's tags")
372 DB.Model(&blog).Association("LocaleTags").Clear()
373 if DB.Model(&blog).Association("LocaleTags").Count() != 0 {
374 t.Errorf("ZH Blog's tags should be cleared when clear ZH Blog's tags")
377 if DB.Model(&blog2).Association("LocaleTags").Count() != 0 {
378 t.Errorf("EN Blog's tags should be cleared")