Grails: могу ли я применить валидатор только для создания (не обновлять / редактировать)

У меня есть класс домена, который должен иметь дату после дня его создания в одном из его полей.

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 ответа

Решение

Вы можете проверить, если id устанавливается как индикатор того, является ли это новый непостоянный экземпляр или существующий постоянный экземпляр:

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

Одним из вариантов может быть указание, какие свойства вы хотите проверить. Из документации:

Метод validate принимает необязательный аргумент 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) если вы можете избежать этого. Это неизбежно приведет к непредвиденным негативным последствиям в будущем, если вы не будете очень осторожны в том, как вы их используете. Если вы можете найти альтернативу, обязательно используйте ее.

Другие вопросы по тегам