1+ package grails.gorm.tests
2+
3+ import grails.persistence.Entity
4+ import org.grails.datastore.mapping.proxy.EntityProxy
5+
6+ class BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec extends GormDatastoreSpec {
7+
8+ void " modified domains object works as expected" () {
9+ given : " I have a Domain OBJECT"
10+ final Referenced object = new Referenced (name : " object" ). save(failOnError : true )
11+ assert ! (object instanceof EntityProxy )
12+
13+ and : " I have another Domain OBJECT with the same name"
14+ final Referenced another = new Referenced (name : " object" )
15+ assert ! (object instanceof EntityProxy )
16+
17+ when : " I try to validate the another object"
18+ another. validate()
19+
20+ then : " another should have an error on name because it is duplicated"
21+ another. hasErrors()
22+ another. errors. hasFieldErrors(" name" )
23+ another. errors. getFieldError(" name" ). codes. contains(" unique.name" )
24+
25+ cleanup :
26+ object?. delete(flush : true )
27+ }
28+
29+ void " modified Referenced domains object works as expected" () {
30+ given : " I have a Domain OBJECT"
31+ final Referenced object = new Referenced (name : " object" ). save(failOnError : true )
32+ assert ! (object instanceof EntityProxy )
33+ and : " a root referencing it"
34+ final Root parent = new Root (ref : object). save(failOnError : true )
35+ assert ! (parent instanceof EntityProxy )
36+
37+ and : " I have another Domain OBJECT with the same name"
38+ final Referenced anotherReferenced = new Referenced (name : " object" )
39+ assert ! (object instanceof EntityProxy )
40+ final Root anotherRoot = new Root (ref : anotherReferenced)
41+ assert ! (parent instanceof EntityProxy )
42+
43+ when : " I try to validate the another object"
44+ anotherRoot. validate()
45+
46+ then : " another should have an error on name because it is duplicated"
47+ anotherRoot. hasErrors()
48+ anotherRoot. errors. hasFieldErrors(" Referenced.name" )
49+ anotherRoot. errors. getFieldError(" Referenced.name" ). codes. contains(" unique.name" )
50+
51+ cleanup :
52+ object?. delete(flush : true )
53+ parent?. delete(flush : true )
54+ }
55+
56+ void " unmodified Referenced proxies object doesnt fail unique constraint checking" () {
57+ given : " I have a Domain OBJECT"
58+ Long ReferencedId , parentId
59+ Root . withNewSession {
60+ Root . withNewTransaction {
61+ final Referenced object = new Referenced (name : " object" ). save(failOnError : true )
62+ final Root parent = new Root (ref : object). save(failOnError : true )
63+
64+ ReferencedId = object. id
65+ parentId = parent. id
66+ }
67+ }
68+ and :
69+ int tries = 20
70+ while (! Root . exists(parentId) && ! Referenced . exists(ReferencedId ) && tries-- > 0 ) {
71+ sleep(50 )
72+ }
73+
74+ and : " I access the parent, forcing the Referenced to be initialized"
75+
76+ def parent = Root . findAll()[0 ]
77+ assert parent. ref instanceof EntityProxy
78+ parent. ref. name == " object"
79+
80+ when : " I try to validate the the parent (which then tries to validate the Referenced)"
81+ parent. validate()
82+
83+ then : " parent.Referenced should not have any errors!"
84+ ! parent. hasErrors()
85+ ! parent. errors. hasFieldErrors(" Referenced.name" )
86+ ! parent. errors. getFieldError(" Referenced.name" ). codes. contains(" unique.name" )
87+
88+ cleanup :
89+
90+ Root . withNewSession {
91+ Root . withNewTransaction {
92+ Referenced . get(ReferencedId )?. delete(flush : true )
93+ Root . get(parentId)?. delete(flush : true )
94+ }
95+ }
96+ tries = 20
97+ while (Root . exists(parentId) && Referenced . exists(ReferencedId ) && tries-- > 0 ) {
98+ sleep(50 )
99+ }
100+ }
101+
102+ @Override
103+ List getDomainClasses () {
104+ [Referenced , Root ]
105+ }
106+ }
107+
108+ @Entity
109+ class Referenced {
110+
111+ String name
112+
113+ static constraints = {
114+ name nullable : false , unique : true
115+ }
116+ }
117+
118+ @Entity
119+ class Root {
120+
121+ Referenced ref
122+
123+ static constraints = {
124+ ref nullable : false
125+ }
126+
127+ static mapping = {
128+ ref lazy : false
129+ id generator : ' snowflake'
130+ }
131+ }
0 commit comments