Grails:我可以将验证器应用于仅创建(不更新/编辑)

时间:2011-05-09 21:43:16

标签: mysql grails calendar grails-validation

我有一个域类,需要在其某个字段中创建日期之后有一个日期。

class myClass {
  Date startDate
  String iAmGonnaChangeThisInSeveralDays
  static constraints = {
    iAmGonnaChangeThisInSeveralDays(nullable:true)
    startDate(validator:{
        def now = new Date()
        def roundedDay = DateUtils.round(now, Calendar.DATE)
        def checkAgainst
        if(roundedDay>now){
            Calendar cal = Calendar.getInstance();
            cal.setTime(roundedDay);
            cal.add(Calendar.DAY_OF_YEAR, -1); // <--
            checkAgainst = cal.getTime();
        }
        else checkAgainst = roundedDay

        return (it >= checkAgainst)
    })
  }
}

所以几天后,当我只更改字符串并调用save时,保存失败,因为验证器正在重新检查日期,现在它已经过去了。我是否可以将验证器设置为仅在创建时触发,或者是否有某些方法可以更改它以检测我们是否正在创建或编辑/更新?

@Rob H. 我不完全确定如何使用你的答案。我有以下代码导致此错误:

myInstance.iAmGonnaChangeThisInSeveralDays = "nachos"
myInstance.save()
if(myInstance.hasErrors()){
  println "This keeps happening because of the stupid date problem"
}

2 个答案:

答案 0 :(得分:13)

您可以检查id是否设置为指示它是新的非持久性实例还是现有持久性实例:

startDate(validator:{ date, obj ->
   if (obj.id) {
      // don't check existing instances
      return
   }
   def now = new Date()
   ...
}

答案 1 :(得分:0)

一个选项可能是指定要验证的属性。来自documentation

  

validate方法接受   可选的List参数   包含属性的名称   应该验证。当一个List   仅传递给validate方法   列表中定义的属性   将被验证。

示例:

// when saving for the first time:
myInstance.startDate = new Date()
if(myInstance.validate() && myInstance.save()) { ... }

// when updating later
myInstance.iAmGonnaChangeThisInSeveralDays = 'New Value'
myInstance.validate(['iAmGonnaChangeThisInSeveralDays'])
if(myInstance.hasErrors() || !myInstance.save(validate: false)) {
    // handle errors
} else {
    // handle success
}

这感觉有些笨拙,因为你绕过了一些内置的Grails善良。如果你只是打电话给save(),你就要小心谨慎,不要绕过域上通常会发生的必要验证。如果有更优雅的解决方案,我会有兴趣看到别人的解决方案。

注意:如果可以避免,我真的不建议使用save(validate: false) 。除非你非常小心你如何使用它,否则它必将导致一些不可预见的负面后果。如果您能找到替代方案,请务必使用它。