grails验证嵌套命令对象不起作用

Posted

技术标签:

【中文标题】grails验证嵌套命令对象不起作用【英文标题】:grails validate nested command object not working 【发布时间】: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 supported(deepValidate 默认为 true)。但是,也许这条规则只适用于域对象而不适用于 Command 对象?还是我只是在这里遗漏了什么?

【问题讨论】:

【参考方案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 失败。 啊,明白了,谢谢你的澄清。显然我读得不够仔细

以上是关于grails验证嵌套命令对象不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Grails、Vaadin 7 和 SpringSecurity:授权不起作用

Grails 监视文件在 Vagrant 虚拟机中运行的 Docker 容器中不起作用

JSON的Grails 2.4命名配置不起作用

Grails 3.1.1 - 当模型类扩展另一个groovy类时,脏检查不起作用

Grails 发送邮件不起作用

Vue3:嵌套 JSON 对象数据的显示不起作用