【问题标题】:grails validate nested command object not workinggrails验证嵌套命令对象不起作用
【发布时间】:2013-04-17 09:22:43
【问题描述】:

我正在使用 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 的实例时,无论部分值如何,它总是返回 true,并且我在 SectionCommand (answerNotBlank) 中的自定义验证器永远不会被调用。从 grails 文档看来,this kind of nested structure is supporteddeepValidate 默认为 true)。但是,也许这条规则只适用于域对象而不适用于 Command 对象?还是我只是在这里遗漏了什么?

【问题讨论】:

    标签: grails grails-2.0 grails-validation command-objects


    【解决方案1】:

    对于 Grails 2.3 及更高版本,我发现Cascade Validation Plugin 很好地解决了这个问题。它定义了一个名为 cascade 的新验证器类型,它完全符合您的期望。安装后,您的示例将变为:

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

    【讨论】:

    • 目前唯一可用的版本是:compile ":cascade-validation:0.1.4"
    • 运行单元测试时,级联约束未注册到 grails。要解决此问题,必须将以下代码添加到测试的 setup() 方法中:ConstrainedProperty.registerNewConstraint(CascadeValidationConstraint.NAME, CascadeValidationConstraint)。来源:github.com/rmorrise/grails-cascade-validation
    【解决方案2】:

    您可以向主命令对象添加自定义验证器

    @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)
        }
    }
    

    【讨论】:

    • 不错!效果很好,但是有没有更干的方法而不是为每个子属性显式定义约束?
    【解决方案3】:

    如果您尝试使用mockForConstraintsTest()unit 测试validation,那么您应该在Config.groovy 中注册command 对象,而不是使用@Validateable,因为现有Grails Bug。详情请参考SO question/answers

    您可以在Config.groovy中注册如下可验证的类

    grails.validateable.classes = 
               [yourpackage.SurveyCommand, yourpackage.SectionCommand] 
    

    【讨论】:

    • 似乎 可以正常工作(在 2.2.1 中)通过在实例化之前调用 mockCommandObject 来测试 @Validatable 命令类的 .validate() 方法,例如mockCommandObject SurveyCommand
    • 同意。这就是我之前提到的 SO 问题/答案的方法。 mockCommandObject 有效,但 mockForConstraintsTest 失败。
    • 啊,明白了,谢谢你的澄清。显然我读得不够仔细
    猜你喜欢
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多