custom Grails validation
Asked Answered
O

2

7

Normally for a Grails domain or command class, you declare your constraints and the framework adds a validate() method that checks whether each of these constraints is valid for the current instance e.g.

class Adult {

  String name
  Integer age

  void preValidate() { 
    // Implementation omitted
  }

  static constraints = {
    name(blank: false)
    age(min: 18)
  }
}

def p = new Person(name: 'bob', age: 21)
p.validate()

In my case I want to make sure that preValidate is always executed before the class is validated. I could achieve this by adding a method

def customValidate() {
  preValidate()
  validate()
}

But then everyone who uses this class needs to remember to call customValidate instead of validate. I can't do this either

def validate() {
  preValidate()
  super.validate()
}

Because validate is not a method of the parent class (it's added by metaprogramming). Is there another way to achieve my goal?

Orr answered 10/4, 2011 at 17:23 Comment(0)
G
2

You should be able to accomplish this by using your own version of validate on the metaclass, when your domain/command class has a preValidate() method. Something similar to the below code in your BootStrap.groovy could work for you:

class BootStrap {

    def grailsApplication   // Set via dependency injection

    def init = { servletContext ->

        for (artefactClass in grailsApplication.allArtefacts) {
            def origValidate = artefactClass.metaClass.getMetaMethod('validate', [] as Class[])
            if (!origValidate) {
                continue
            }

            def preValidateMethod = artefactClass.metaClass.getMetaMethod('preValidate', [] as Class[])
            if (!preValidateMethod) {
                continue
            }

            artefactClass.metaClass.validate = {
                preValidateMethod.invoke(delegate)
                origValidate.invoke(delegate)
            }
        }
    }

    def destroy = {
    }
}
Grace answered 10/4, 2011 at 22:3 Comment(0)
B
2

You may be able to accomplish your goal using the beforeValidate() event. It's described in the 1.3.6 Release Notes.

Brom answered 25/5, 2011 at 14:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.