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 und开发者_如何学Goerstand 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.
You can indeed change constraints at runtime.
ConstrainedProperty constrainedProperty = Address.constraints.zipCode
constrainedProperty.setSize(5..6)
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.
Think that maybe I'm not understanding as you could also look at just doing this as domain level validation... could you not?
精彩评论