polymorphic_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. package gorm_test
  2. import (
  3. "reflect"
  4. "sort"
  5. "testing"
  6. )
  7. type Cat struct {
  8. Id int
  9. Name string
  10. Toy Toy `gorm:"polymorphic:Owner;"`
  11. }
  12. type Dog struct {
  13. Id int
  14. Name string
  15. Toys []Toy `gorm:"polymorphic:Owner;"`
  16. }
  17. type Hamster struct {
  18. Id int
  19. Name string
  20. PreferredToy Toy `gorm:"polymorphic:Owner;polymorphic_value:hamster_preferred"`
  21. OtherToy Toy `gorm:"polymorphic:Owner;polymorphic_value:hamster_other"`
  22. }
  23. type Toy struct {
  24. Id int
  25. Name string
  26. OwnerId int
  27. OwnerType string
  28. }
  29. var compareToys = func(toys []Toy, contents []string) bool {
  30. var toyContents []string
  31. for _, toy := range toys {
  32. toyContents = append(toyContents, toy.Name)
  33. }
  34. sort.Strings(toyContents)
  35. sort.Strings(contents)
  36. return reflect.DeepEqual(toyContents, contents)
  37. }
  38. func TestPolymorphic(t *testing.T) {
  39. cat := Cat{Name: "Mr. Bigglesworth", Toy: Toy{Name: "cat toy"}}
  40. dog := Dog{Name: "Pluto", Toys: []Toy{{Name: "dog toy 1"}, {Name: "dog toy 2"}}}
  41. DB.Save(&cat).Save(&dog)
  42. if DB.Model(&cat).Association("Toy").Count() != 1 {
  43. t.Errorf("Cat's toys count should be 1")
  44. }
  45. if DB.Model(&dog).Association("Toys").Count() != 2 {
  46. t.Errorf("Dog's toys count should be 2")
  47. }
  48. // Query
  49. var catToys []Toy
  50. if DB.Model(&cat).Related(&catToys, "Toy").RecordNotFound() {
  51. t.Errorf("Did not find any has one polymorphic association")
  52. } else if len(catToys) != 1 {
  53. t.Errorf("Should have found only one polymorphic has one association")
  54. } else if catToys[0].Name != cat.Toy.Name {
  55. t.Errorf("Should have found the proper has one polymorphic association")
  56. }
  57. var dogToys []Toy
  58. if DB.Model(&dog).Related(&dogToys, "Toys").RecordNotFound() {
  59. t.Errorf("Did not find any polymorphic has many associations")
  60. } else if len(dogToys) != len(dog.Toys) {
  61. t.Errorf("Should have found all polymorphic has many associations")
  62. }
  63. var catToy Toy
  64. DB.Model(&cat).Association("Toy").Find(&catToy)
  65. if catToy.Name != cat.Toy.Name {
  66. t.Errorf("Should find has one polymorphic association")
  67. }
  68. var dogToys1 []Toy
  69. DB.Model(&dog).Association("Toys").Find(&dogToys1)
  70. if !compareToys(dogToys1, []string{"dog toy 1", "dog toy 2"}) {
  71. t.Errorf("Should find has many polymorphic association")
  72. }
  73. // Append
  74. DB.Model(&cat).Association("Toy").Append(&Toy{
  75. Name: "cat toy 2",
  76. })
  77. var catToy2 Toy
  78. DB.Model(&cat).Association("Toy").Find(&catToy2)
  79. if catToy2.Name != "cat toy 2" {
  80. t.Errorf("Should update has one polymorphic association with Append")
  81. }
  82. if DB.Model(&cat).Association("Toy").Count() != 1 {
  83. t.Errorf("Cat's toys count should be 1 after Append")
  84. }
  85. if DB.Model(&dog).Association("Toys").Count() != 2 {
  86. t.Errorf("Should return two polymorphic has many associations")
  87. }
  88. DB.Model(&dog).Association("Toys").Append(&Toy{
  89. Name: "dog toy 3",
  90. })
  91. var dogToys2 []Toy
  92. DB.Model(&dog).Association("Toys").Find(&dogToys2)
  93. if !compareToys(dogToys2, []string{"dog toy 1", "dog toy 2", "dog toy 3"}) {
  94. t.Errorf("Dog's toys should be updated with Append")
  95. }
  96. if DB.Model(&dog).Association("Toys").Count() != 3 {
  97. t.Errorf("Should return three polymorphic has many associations")
  98. }
  99. // Replace
  100. DB.Model(&cat).Association("Toy").Replace(&Toy{
  101. Name: "cat toy 3",
  102. })
  103. var catToy3 Toy
  104. DB.Model(&cat).Association("Toy").Find(&catToy3)
  105. if catToy3.Name != "cat toy 3" {
  106. t.Errorf("Should update has one polymorphic association with Replace")
  107. }
  108. if DB.Model(&cat).Association("Toy").Count() != 1 {
  109. t.Errorf("Cat's toys count should be 1 after Replace")
  110. }
  111. if DB.Model(&dog).Association("Toys").Count() != 3 {
  112. t.Errorf("Should return three polymorphic has many associations")
  113. }
  114. DB.Model(&dog).Association("Toys").Replace(&Toy{
  115. Name: "dog toy 4",
  116. }, []Toy{
  117. {Name: "dog toy 5"}, {Name: "dog toy 6"}, {Name: "dog toy 7"},
  118. })
  119. var dogToys3 []Toy
  120. DB.Model(&dog).Association("Toys").Find(&dogToys3)
  121. if !compareToys(dogToys3, []string{"dog toy 4", "dog toy 5", "dog toy 6", "dog toy 7"}) {
  122. t.Errorf("Dog's toys should be updated with Replace")
  123. }
  124. if DB.Model(&dog).Association("Toys").Count() != 4 {
  125. t.Errorf("Should return three polymorphic has many associations")
  126. }
  127. // Delete
  128. DB.Model(&cat).Association("Toy").Delete(&catToy2)
  129. var catToy4 Toy
  130. DB.Model(&cat).Association("Toy").Find(&catToy4)
  131. if catToy4.Name != "cat toy 3" {
  132. t.Errorf("Should not update has one polymorphic association when Delete a unrelated Toy")
  133. }
  134. if DB.Model(&cat).Association("Toy").Count() != 1 {
  135. t.Errorf("Cat's toys count should be 1")
  136. }
  137. if DB.Model(&dog).Association("Toys").Count() != 4 {
  138. t.Errorf("Dog's toys count should be 4")
  139. }
  140. DB.Model(&cat).Association("Toy").Delete(&catToy3)
  141. if !DB.Model(&cat).Related(&Toy{}, "Toy").RecordNotFound() {
  142. t.Errorf("Toy should be deleted with Delete")
  143. }
  144. if DB.Model(&cat).Association("Toy").Count() != 0 {
  145. t.Errorf("Cat's toys count should be 0 after Delete")
  146. }
  147. if DB.Model(&dog).Association("Toys").Count() != 4 {
  148. t.Errorf("Dog's toys count should not be changed when delete cat's toy")
  149. }
  150. DB.Model(&dog).Association("Toys").Delete(&dogToys2)
  151. if DB.Model(&dog).Association("Toys").Count() != 4 {
  152. t.Errorf("Dog's toys count should not be changed when delete unrelated toys")
  153. }
  154. DB.Model(&dog).Association("Toys").Delete(&dogToys3)
  155. if DB.Model(&dog).Association("Toys").Count() != 0 {
  156. t.Errorf("Dog's toys count should be deleted with Delete")
  157. }
  158. // Clear
  159. DB.Model(&cat).Association("Toy").Append(&Toy{
  160. Name: "cat toy 2",
  161. })
  162. if DB.Model(&cat).Association("Toy").Count() != 1 {
  163. t.Errorf("Cat's toys should be added with Append")
  164. }
  165. DB.Model(&cat).Association("Toy").Clear()
  166. if DB.Model(&cat).Association("Toy").Count() != 0 {
  167. t.Errorf("Cat's toys should be cleared with Clear")
  168. }
  169. DB.Model(&dog).Association("Toys").Append(&Toy{
  170. Name: "dog toy 8",
  171. })
  172. if DB.Model(&dog).Association("Toys").Count() != 1 {
  173. t.Errorf("Dog's toys should be added with Append")
  174. }
  175. DB.Model(&dog).Association("Toys").Clear()
  176. if DB.Model(&dog).Association("Toys").Count() != 0 {
  177. t.Errorf("Dog's toys should be cleared with Clear")
  178. }
  179. }
  180. func TestNamedPolymorphic(t *testing.T) {
  181. hamster := Hamster{Name: "Mr. Hammond", PreferredToy: Toy{Name: "bike"}, OtherToy: Toy{Name: "treadmill"}}
  182. DB.Save(&hamster)
  183. hamster2 := Hamster{}
  184. DB.Preload("PreferredToy").Preload("OtherToy").Find(&hamster2, hamster.Id)
  185. if hamster2.PreferredToy.Id != hamster.PreferredToy.Id || hamster2.PreferredToy.Name != hamster.PreferredToy.Name {
  186. t.Errorf("Hamster's preferred toy couldn't be preloaded")
  187. }
  188. if hamster2.OtherToy.Id != hamster.OtherToy.Id || hamster2.OtherToy.Name != hamster.OtherToy.Name {
  189. t.Errorf("Hamster's other toy couldn't be preloaded")
  190. }
  191. // clear to omit Toy.Id in count
  192. hamster2.PreferredToy = Toy{}
  193. hamster2.OtherToy = Toy{}
  194. if DB.Model(&hamster2).Association("PreferredToy").Count() != 1 {
  195. t.Errorf("Hamster's preferred toy count should be 1")
  196. }
  197. if DB.Model(&hamster2).Association("OtherToy").Count() != 1 {
  198. t.Errorf("Hamster's other toy count should be 1")
  199. }
  200. // Query
  201. var hamsterToys []Toy
  202. if DB.Model(&hamster).Related(&hamsterToys, "PreferredToy").RecordNotFound() {
  203. t.Errorf("Did not find any has one polymorphic association")
  204. } else if len(hamsterToys) != 1 {
  205. t.Errorf("Should have found only one polymorphic has one association")
  206. } else if hamsterToys[0].Name != hamster.PreferredToy.Name {
  207. t.Errorf("Should have found the proper has one polymorphic association")
  208. }
  209. if DB.Model(&hamster).Related(&hamsterToys, "OtherToy").RecordNotFound() {
  210. t.Errorf("Did not find any has one polymorphic association")
  211. } else if len(hamsterToys) != 1 {
  212. t.Errorf("Should have found only one polymorphic has one association")
  213. } else if hamsterToys[0].Name != hamster.OtherToy.Name {
  214. t.Errorf("Should have found the proper has one polymorphic association")
  215. }
  216. hamsterToy := Toy{}
  217. DB.Model(&hamster).Association("PreferredToy").Find(&hamsterToy)
  218. if hamsterToy.Name != hamster.PreferredToy.Name {
  219. t.Errorf("Should find has one polymorphic association")
  220. }
  221. hamsterToy = Toy{}
  222. DB.Model(&hamster).Association("OtherToy").Find(&hamsterToy)
  223. if hamsterToy.Name != hamster.OtherToy.Name {
  224. t.Errorf("Should find has one polymorphic association")
  225. }
  226. // Append
  227. DB.Model(&hamster).Association("PreferredToy").Append(&Toy{
  228. Name: "bike 2",
  229. })
  230. DB.Model(&hamster).Association("OtherToy").Append(&Toy{
  231. Name: "treadmill 2",
  232. })
  233. hamsterToy = Toy{}
  234. DB.Model(&hamster).Association("PreferredToy").Find(&hamsterToy)
  235. if hamsterToy.Name != "bike 2" {
  236. t.Errorf("Should update has one polymorphic association with Append")
  237. }
  238. hamsterToy = Toy{}
  239. DB.Model(&hamster).Association("OtherToy").Find(&hamsterToy)
  240. if hamsterToy.Name != "treadmill 2" {
  241. t.Errorf("Should update has one polymorphic association with Append")
  242. }
  243. if DB.Model(&hamster2).Association("PreferredToy").Count() != 1 {
  244. t.Errorf("Hamster's toys count should be 1 after Append")
  245. }
  246. if DB.Model(&hamster2).Association("OtherToy").Count() != 1 {
  247. t.Errorf("Hamster's toys count should be 1 after Append")
  248. }
  249. // Replace
  250. DB.Model(&hamster).Association("PreferredToy").Replace(&Toy{
  251. Name: "bike 3",
  252. })
  253. DB.Model(&hamster).Association("OtherToy").Replace(&Toy{
  254. Name: "treadmill 3",
  255. })
  256. hamsterToy = Toy{}
  257. DB.Model(&hamster).Association("PreferredToy").Find(&hamsterToy)
  258. if hamsterToy.Name != "bike 3" {
  259. t.Errorf("Should update has one polymorphic association with Replace")
  260. }
  261. hamsterToy = Toy{}
  262. DB.Model(&hamster).Association("OtherToy").Find(&hamsterToy)
  263. if hamsterToy.Name != "treadmill 3" {
  264. t.Errorf("Should update has one polymorphic association with Replace")
  265. }
  266. if DB.Model(&hamster2).Association("PreferredToy").Count() != 1 {
  267. t.Errorf("hamster's toys count should be 1 after Replace")
  268. }
  269. if DB.Model(&hamster2).Association("OtherToy").Count() != 1 {
  270. t.Errorf("hamster's toys count should be 1 after Replace")
  271. }
  272. // Clear
  273. DB.Model(&hamster).Association("PreferredToy").Append(&Toy{
  274. Name: "bike 2",
  275. })
  276. DB.Model(&hamster).Association("OtherToy").Append(&Toy{
  277. Name: "treadmill 2",
  278. })
  279. if DB.Model(&hamster).Association("PreferredToy").Count() != 1 {
  280. t.Errorf("Hamster's toys should be added with Append")
  281. }
  282. if DB.Model(&hamster).Association("OtherToy").Count() != 1 {
  283. t.Errorf("Hamster's toys should be added with Append")
  284. }
  285. DB.Model(&hamster).Association("PreferredToy").Clear()
  286. if DB.Model(&hamster2).Association("PreferredToy").Count() != 0 {
  287. t.Errorf("Hamster's preferred toy should be cleared with Clear")
  288. }
  289. if DB.Model(&hamster2).Association("OtherToy").Count() != 1 {
  290. t.Errorf("Hamster's other toy should be still available")
  291. }
  292. DB.Model(&hamster).Association("OtherToy").Clear()
  293. if DB.Model(&hamster).Association("OtherToy").Count() != 0 {
  294. t.Errorf("Hamster's other toy should be cleared with Clear")
  295. }
  296. }