简体   繁体   中英

Groovy / Grails: Enhance a Static Closure

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.

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.

认为我可能不太理解,因为您也可以将其视为域级别验证...可以吗?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM