tags:

views:

321

answers:

1

Hey People of Groovy,

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.

Thanks for your ideas
/litius

+1  A: 

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.

Jean Barmash
I agree, that domain constraints should not be modifiable, once the app is up and running, however for plugin purposes, I think they should be open.`shared constraints` would require user manually *enter* a property into a static block.anyway thanks for digging into
litius
Found this thread that might be relevant here. http://old.nabble.com/Is-it-possible-to-inject-constraints-dynamically-on-domain-classes--td24489941.html
Jean Barmash