【问题标题】:Grails: can I make a validator apply to create only (not update/edit)Grails:我可以让验证器仅适用于创建(不更新/编辑)
【发布时间】:2011-05-09 21:43:15
【问题描述】:

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

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

【问题讨论】:

  • startDate 会在初始保存后更新吗?

标签: mysql grails calendar grails-validation


【解决方案1】:

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

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

【讨论】:

  • 这正是我所需要的 + 一个相当不错的 hack。
【解决方案2】:

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

验证方法接受一个 可选的 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
}

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

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

【讨论】:

  • 不完全确定如何使用它;请查看我对原始问题的修改。
  • @Mikey - 更新了我的答案。我需要运行一个快速测试以确保它是正确的。如果没有,可以将其更新为使用 save(validate: false) 以避免 Grails 在您自己完成之后调用 validate()
  • @Mikey - 在进行了一些测试后进行了另一次更新。也许它会为你工作。
  • 酷我要过着超级危险的生活,只是将我损坏的代码更改为包含 validate: false
  • @Mikey - FWIW,是的,这确实感觉很危险。我什至不愿推荐在我的答案中使用它。还有其他选择。您可以在域上有一个临时属性,指示是否应验证 startDate,然后在自定义验证器中使用它。
猜你喜欢
  • 1970-01-01
  • 2017-01-04
  • 2019-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多