Перейти к основному содержанию

Система валидации

Ziva выполняет проверку пользовательского ввода непосредственно в InputTask. Как только пользователь нажимает Enter, задача вызывает валидатор и, при необходимости, возвращает сообщение об ошибке прямо в интерфейс.

Базовое использование

v := ziva.DefaultValidators

email := ziva.NewInputTask("Email", "Введите адрес:").
    WithInputType(ziva.InputTypeEmail).
    WithValidator(v.Email())
Если email некорректен, пользователь увидит подсказку и сможет исправить значение без выхода из очереди.

Что такое валидатор

Валидатор — это значение с двумя методами:
type Validator interface {
    Validate(input string) error
    Description() string
}
Возвращаемая ошибка попадает в интерфейс, описание используется для пояснения требований. Вам не нужно импортировать интерфейс — достаточно объявить тип с такими методами.

Подключение встроенных валидаторов

v := ziva.DefaultValidators

username := ziva.NewInputTask("Имя", "3-20 символов, латиница")
username.WithValidator(v.Username())

port := ziva.NewInputTask("Порт", "1..65535").
    WithInputType(ziva.InputTypeNumber).
    WithValidator(v.Port())
Список всех доступных проверок смотрите в разделе Встроенные валидаторы.

Опциональные поля

Если значение может быть пустым:
phone := ziva.NewInputTask("Телефон", "Необязательно")
phone.WithAllowEmpty(true)
phone.WithValidator(funcValidator)
Комбинируйте WithAllowEmpty(true) с валидатором, который корректно обрабатывает пустую строку (например, OptionalEmail()).

Кастомные валидаторы

type evenNumber struct{}

func (evenNumber) Validate(input string) error {
    n, err := strconv.Atoi(strings.TrimSpace(input))
    if err != nil {
        return errors.New("введите целое число")
    }
    if n%2 != 0 {
        return errors.New("нужно чётное число")
    }
    return nil
}

func (evenNumber) Description() string {
    return "Чётное целое число"
}

code := ziva.NewInputTask("Чётный ID", "Введите значение:")
code.WithInputType(ziva.InputTypeNumber)
code.WithValidator(evenNumber{})
Таким образом можно описывать любую бизнес-логику: от проверки контрольных сумм до валидации с внешними сервисами.

Несколько проверок подряд

Часто нужно объединять условия:
v := ziva.DefaultValidators

validationChain := []interface {
    Validate(string) error
    Description() string
}{
    v.Required(),
    v.MinLength(3),
    v.MaxLength(20),
    v.AlphaNumeric(),
}

validator := compositeValidator(validationChain)

login := ziva.NewInputTask("Логин", "3-20 латинских символов")
login.WithValidator(validator)
compositeValidator — удобная обёртка (см. пример в разделе встроенных валидаторов). Можно написать свою, чтобы красиво объединять сообщения об ошибках.

Обработка результата после очереди

Даже если поле прошло валидацию, дополнительно проверяйте его после queue.Run() — особенно если требуется обращение к внешним сервисам или БД.
queue := ziva.NewQueue("Регистрация")
queue.AddTasks(login, email)
if err := queue.Run(); err != nil {
    return err
}

// Дополнительная проверка уникальности
if exists(login.GetValue()) {
    return fmt.Errorf("логин %q уже используется", login.GetValue())
}

Лучшие практики

  • Формулируйте сообщения об ошибке так, чтобы пользователь понимал, как исправить ввод.
  • Для сложных правил описывайте требования через Description() — Ziva покажет их как подсказку.
  • Комбинируйте InputTask с FuncTask, если нужно выполнить длительную проверку (например, запрос к API) и показать подробный результат.
  • Учитывайте локаль: если используете числа, не забудьте обрезать пробелы и заменить запятые на точки (в случае необходимости — сделайте собственный валидатор).
Подробнее о создании собственных валидаторов — в разделе Кастомные валидаторы.
I