Вопрос по – Условная валидация Grails или пользовательский валидатор с параметром NULL.

6

У меня есть форма, чтобы создать место. В зависимости от страны, поле провинции (штат, область) является обязательным или нет.

Когда это не требуется, я хочу быть пустой, а не пустой строкой. У меня есть код, который делает все пустые поля формы, нуль:

def newparams = [:]
        place = new Place()
        params.each() { k, v ->
            if (v instanceof String && place.hasProperty(k)) {
                if (!v.trim().length()) {
                    newparams[k] = null
                } else {
                    newparams[k] = v
                }
            }
        }

        place = new Place(newparams)
        place.validate()

Теперь в домене мест у меня есть валидатор по провинции:

province validator:  {val, obj -> if (obj.country in obj.requiresRegionCountries() && !obj.province) return [province.required]}

С этим правилом я всегда получаю "провинция" не может быть нулевой " даже если это требуется или нет.

Я думаю, что это потому, что обнуляемый валидатор, который по умолчанию установлен в false.

Если я добавляю nullable: true, то даже если требуется провинция, пользовательский валидатор пропускается, и его можно сохранить с пустой провинцией (я думаю, это потому, что его экземпляр создается с нулем)

Теперь мне нужно как-то мой пользовательский валидатор, а также возможность указать обнуляемое значение в моем валидаторе, что-то вроде этого:

province validator:  {val, obj -> 
  if (obj.country in obj.requiresRegionCountries() && !obj.province) { 
    nullable: false
    return [province.required] }
  else {
    nullable: true
  }
}

Как я могу добиться этого в Grails 2.0.3?

Ваш Ответ

2   ответа
5

Я не могу сказать с помощью кода, который вы вставили, но если ваша проблема заключается в том, что проверка по умолчанию не позволяет провинции иметь нулевое значение, вы пытались явно разрешить провинции быть нулевым? Вам разрешено несколько валидаторов для каждого поля. Итак, вернемся к исходному коду, просто укажите валидатор, который может принимать значения NULL:

province nullable: true, validator:  {val, obj -> 
  if (obj != null && obj.country in obj.requiresRegionCountries() && !obj.province) 
    return [province.required]
}

РЕДАКТИРОВАТЬ:  В пользовательском валидаторе может также потребоваться защита от значения obj, равного нулю, в условии if.

РЕДАКТИРОВАТЬ 2: Демонстрационный проект, показывающий вышеупомянутую проверку работоспособности на Grails 2.0.4

class Place {
String country
Province province

  static constraints = {
    province (nullable: true, validator: {val, obj ->
        if (obj.country == 'Canada' && !val) return ['province.required']
    })
  }
}

Контроллер ...

 class MainController {
  def index() {
    def place = new Place(country: 'Canada')
    if (!place.validate()) {
        render "need province<br/>" + place.errors
    } else {
        render "cool"
    }

Таким образом, идея заключается в том, что у меня есть фиктивный контроллер, где я могу вызвать действие index, которое жестко задано для создания экземпляра домена Place, аналогичного вашему примеру. Обратите внимание, что я определил только строку страны, поэтому я могу использовать свою логику для пользовательской проверки. Я не определял провинцию при создании экземпляра Place, поэтому он должен быть нулевым. При таком сценарии на странице ответа будет напечатано следующее ...

Выходной фрагмент ...

need province 
grails.validation.ValidationErrors: 1 .... does not pass custom validation]

Если я удалю ограничение nullable: true из Place, то ошибка будет нулевым значением, как и ожидалось ...

Выходной фрагмент ...

need province
grails.validation.ValidationErrors: 1 .... cannot be null]
Этот код: статические ограничения = {провинция (обнуляемый: истина, валидатор: {val, obj -> if (obj.country == "Канада" & amp; & amp;! Val) return ["провинция.required" » )} в Grails 2.0.3, если val равен нулю, валидатор пройдет и пользовательский валидатор никогда не будет вызван. Но я обнаружил, что если сначала поставить пользовательский валидатор, то обнуляемый, все работает нормально Eduard
Спасибо за ваш ответ, но есть проблема. Если я установил значение nullable и place.province будет иметь значение null, то пользовательская проверка будет полностью пропущена. Я хочу быть обнуляемым для некоторых стран, но не для других. Eduard
Может быть, это ошибка Grails 2.0.3. Я использую 2.0.4, и он работает для меня с простым демонстрационным проектом, который я создал, который я вставлю в мой ответ выше, чтобы вы могли сравнить
Для ясности: если я не укажу nullable true и поле будет равно null, ошибка "не может быть null" брошен и мой пользовательский валидатор не выполняется. Если я добавлю nullable: true и значение равно null, проверка пройдет успешно, мой пользовательский валидатор не будет выполнен. Я хочу быть нулевым для одних стран и не нулевым для других. Это то, что я не могу сделать с текущим поведением. Eduard
12

После долгих исследований и отзывов я нашел 2 решения, которые работают. Один в контроллере. Не добавляйте проверки в модель и добавляйте их динамически из контроллера:

class PlacesController {
  def create() {
  def place = new Place(params.address)
  if (place.country in placesThatRequiresProvinceArray) {
      place.constrains.province.nullable = false
  } else {
      place.constrains.province.nullable = true
  }

}

Другое решение - это то, что было предложено Tri в этом потоке, но поместите пользовательский валидатор перед ограничением Nullable (иначе пользовательский валидатор не будет вызываться для нулевых значений):

static constraints = {
  province (validator: {val, obj ->
    if (obj.country == 'Canada' && !val)
      return ['province.required']
  }, nullable: true)
}

Похожие вопросы