7

我有一个域类,它需要在它的一个字段中创建它的那一天之后有一个日期。

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"
}
4

2 回答 2

14

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

startDate(validator:{ date, obj ->
   if (obj.id) {
      // don't check existing instances
      return
   }
   def now = new Date()
   ...
}
于 2011-05-09T22:32:44.737 回答
0

一种选择可能是指定要验证的属性。从文档中:

validate 方法接受一个可选的 List 参数,该参数可能包含应验证的属性的名称。将 List 传递给 validate 方法时,只会验证 List 中定义的属性。

例子:

// 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
}

这感觉有点 hacky,因为你绕过了一些内置的 Grails 优点。您需要谨慎,不要绕过域上的任何必要验证,如果您只调用save(). 如果有更优雅的解决方案,我很想看看其他人的解决方案。

注意:如果可以避免的话,我真的不建议使用。save(validate: false)除非您对如何使用它非常小心,否则它肯定会在未来造成一些无法预料的负面后果。如果您能找到替代方案,请务必使用它。

于 2011-05-09T21:57:41.170 回答