Grails验证嵌套命令对象不工作



我正在使用grails 2.2.1并尝试验证嵌套命令结构。下面是我的命令对象的简化版本:

@Validateable
class SurveyCommand {
    SectionCommand useful
    SectionCommand recommend
    SurveyCommand() {
        useful = new SectionCommand(
                question: 'Did you find this useful?',
                isRequired: true)
        recommend = new SectionCommand(
                question: 'Would you recommend to someone else?',
                isRequired: false)
    }
}
@Validateable
class SectionCommand {
    String question
    String answer
    boolean isRequired
    static constraints = {
        answer(validator: answerNotBlank, nullable: true)
    }
    static answerNotBlank = { String val, SectionCommand obj ->
        if(obj.isRequired) {
            return val != null && !val.isEmpty()
        }
    }
}

当我尝试验证SurveyCommand的实例时,无论section值如何,它总是返回true,并且我在SectionCommand (answerNotBlank)中的自定义验证器从未调用。从grails文档来看,似乎支持这种嵌套结构(deepValidate默认为true)。然而,也许这条规则只适用于域对象,而不是命令对象?还是我漏掉了什么?

对于Grails 2.3和以后的版本,我发现级联验证插件很好地解决了这个问题。它定义了一个名为cascade的新验证器类型,它的功能完全符合您的期望。安装后,您的示例将变成:

class SurveyCommand {
    ...
    static constraints = {
        useful(cascade: true)
        recommend(cascade: true)
    }
}

您可以在主命令对象中添加一个自定义验证器

@Validateable
class SurveyCommand {
    SectionCommand useful
    SectionCommand recommend
    static subValidator = {val, obj ->
        return val.validate() ?: 'not.valid'
    }
    static constraints = {
        useful(validator: subValidator)
        recommend(validator: subValidator)
    }
    SurveyCommand() {
        useful = new SectionCommand(
            question: 'Did you find this useful?',
            isRequired: true)
        recommend = new SectionCommand(
            question: 'Would you recommend to someone else?',
            isRequired: false)
    }
}

如果您试图使用mockForConstraintsTest()unit测试中测试validation,那么您应该在Config.groovy中注册command对象,而不是使用@Validateable,因为现有的Grails错误。详细信息请参考以下问题/答案。

可以在Config.groovy

中注册validateable类,如下所示
grails.validateable.classes = 
           [yourpackage.SurveyCommand, yourpackage.SectionCommand] 

最新更新