2011-04-10 62 views
7

通常,對於Grails域或命令類,您聲明瞭約束,並且框架添加了一個validate()方法,用於檢查每個約束是否對當前實例有效,例如,自定義Grails驗證

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() 

在我的情況下,我想確保preValidate始終在類驗證之前執行。我可以通過添加一個方法

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

但後來大家誰使用這個類需要記住實現這個調用customValidate而不是validate。我不能做到這一點無論

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

因爲validate不是父類的方法(它是由元編程添加)。有另一種方法來實現我的目標嗎?

回答

2

當你的域名/命令類有一個preValidate()方法時,你應該能夠通過在元類上使用你自己的驗證版本來實現這一點。類似於下面的代碼的東西在你的BootStrap.groovy可以爲你工作:

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 = { 
    } 
} 
2

您可以完成使用beforeValidate()事件你的目標。它在1.3.6 Release Notes中有描述。