Reputation: 22549
I am looking for a way to modify/change an existing closure. However, I do not wish to overwrite it; instead I would like to enhance it.
Here is a quick example. Let's say we have an Address object:
class Address {
String street
String city
String state
String zipCode
static constraints = {
street( nullable:true )
city( blank:false )
state( size:2..2 )
}
}
It would be a good example, because it is also a valid Grails domain object. What I am looking to do is to add another constraint at runtime / dynamically to the Address class:
class Address {
String street
String city
String state
String zipCode
static constraints = {
street( nullable: true )
city( blank: false )
state( size: 2..2 )
zipCode( size: 5..6 )
}
}
Notice that new zipCode
constraint?
I understand that I can change the constraints all together by overriding it through the metaClass
; however, the goal here is not to hurt anybody in a process, hence I just want to add to the existing closure.
Upvotes: 2
Views: 1560
Reputation: 654
Think that maybe I'm not understanding as you could also look at just doing this as domain level validation... could you not?
Upvotes: 0
Reputation: 31
You can indeed change constraints at runtime.
ConstrainedProperty constrainedProperty = Address.constraints.zipCode
constrainedProperty.setSize(5..6)
Upvotes: 3
Reputation: 4789
I think you might be out of luck here. From what I can tell, Grails developers don't want you to modify constraints at runtime. Constraints are stored in
org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass
where constraints themselves are stored as a private map, with the only accessor
public Map getConstrainedProperties()
{
return Collections.unmodifiableMap(this.constraints);
}
The constraints closure is processed by org.codehaus.groovy.grails.validation.ConstrainedPropertyBuilder.
You can obviously write your own DomainClass class that has a modifiable constraints object, and inject that one into Spring-based initialization, but I suspect that's a path that you might not want to take.
Additional thought - I don't know the specific example for zipCode constraint, but many of the constraints enforce database column constraints, so adding those at runtime can probably lead to weird behavior. I think using custom constraint validators would be easier for you to avoid weird database bugs.
Update
Looking on it some more, I found DefaultGrailsDomainClass has refreshConstraints() method, which seems to force re-evaluation of the constraints closure, although I still am not sure if you can modify the closure itself, or why this functionality exists in the first place.
In 1.2 Grails added shared constraints - I wonder if you could create a zipCode shared constraint, modify it somehow, and then call refresh.
Upvotes: 2