【问题标题】:Where does Grail's errors property come from?Grail 的错误属性从何而来?
【发布时间】:2013-02-27 01:40:32
【问题描述】:

Grails 在数据绑定方面存在一个错误,即当您处理错误的数字输入时,它会引发强制转换异常。 JIRA:http://jira.grails.org/browse/GRAILS-6766

为了解决这个问题,我编写了以下代码来手动处理位于 src/groovy 的 POGO 类 Foo 上的数字输入

void setPrice(String priceStr)
{
    this.priceString = priceStr

    // Remove $ and , 
    priceStr = priceStr.trim().replaceAll(java.util.regex.Matcher.quoteReplacement('$'),'').replaceAll(',','')

    if (!priceStr.isDouble()) {
        errors.reject(
            'trade.price.invalidformat',
            [priceString] as Object[],
            'Price:[{0}] is an invalid price.')

        errors.rejectValue(
            'price',
            'trade.price.invalidformat')
    } else {
        this.price = priceStr.toDouble();
    }
}

下面会在errors.reject() 行引发空引用异常。

foo.price = "asdf" // throws null reference on errors.reject()
foo.validate()

但是,我可以说:

foo.validate()
foo.price = "asdf" // no Null exception
foo.hasErrors() // false
foo.validate()
foo.hasErrors() // true

validate() 被调用时错误从何而来? 有没有办法在不先调用validate() 的情况下添加errors 属性?

【问题讨论】:

    标签: validation grails grails-2.0


    【解决方案1】:

    我不能确切地告诉你为什么,但你需要显式调用getErrors(),而不是像属性一样以errors 访问它。出于某种原因,Groovy 没有为它调用方法。所以将setPrice()中的reject行改为

    getErrors().reject(
            'trade.price.invalidformat',
            [priceString] as Object[],
            'Price:[{0}] is an invalid price.')
    
    getErrors().rejectValue(
            'price',
            'trade.price.invalidformat')
    

    这是确保Errors 对象存在于您的方法中的最简单方法。您可以check out the code 将验证相关的方法添加到您的域类中。

    【讨论】:

      【解决方案2】:

      AST 转换处理@Validateableaugments the class with, among other things

      • 一个名为errors的字段
      • 公共方法getErrorssetErrorsclearErrorshasErrors

      getErrors 方法会延迟设置 errors 字段(如果尚未设置)。所以看起来正在发生的事情是在同一个类中对 errors 的访问被视为字段访问而不是 Java Bean 属性访问,并且绕过了延迟初始化。

      所以解决方法似乎是使用getErrors() 而不仅仅是errors

      【讨论】:

      • 嗯,我一定是掩饰了 POGO 位并假设它是一个域类
      • @doelleri 我认为相同的转换也适用于域类,您链接到的代码仅针对那些在编译时未增强的域类触发(这可能发生在开发模式自动重新编译时) )。你应该被接受,我只是在解决你的“我不能确切地告诉你为什么”:-)
      【解决方案3】:

      错误会动态添加到您的可验证类(域类和具有注释 @Validateable 的类)中。

      允许开发人员设置字符串而不是数字似乎不是一个好方法。此外,您的验证仅适用于该特定类。

      我认为更好的方法是为数字注册一个自定义属性编辑器。这是带有日期的a example,它可以将String(来自表单)转换为Date,格式类似于dd/MM/yyyy。这个想法是一样的,因为您将强制您的号码是可解析的(例如,Integer.parseInt() 将抛出异常)。

      在您的域类中,使用数字类型而不是字符串,因此代码开发人员将不允许存储非数字值。

      【讨论】:

        猜你喜欢
        • 2021-09-25
        • 1970-01-01
        • 2019-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-21
        • 2012-05-15
        • 1970-01-01
        相关资源
        最近更新 更多