пятница, 13 января 2012 г.

Валидация данных в Mojolicious

Написал небольшой плагин для Mojolicious  - Mojolicious::Plugin::ValidateTiny. По сути - это обертка над Validate::Tiny с дополнительными удобными плюшками.

Для валидации входящий параметров мы просто используем хелпер:
$self->do_validation($validate_rules);
$validate_rules - это описание проверок в формате Validate::Tiny.

По-умолчанию, включена опция "autofields", которая позволяет использовать сокращенный вариант правил проверки. И вместо:
  {  
     fields => ['user', 'pass'],
     checks => [user => is_required(), pass => is_required()] 
  }
можно писать:
 [ user => is_required(), pass => is_required() ]
и fields автоматически заполнятся исходя из описания проверок.

Также очень полезна опции "explicit", которая обязывает нас описать явно правила валидации для каждого поля. По-умолчанию, выключена, но в своих проекта я всегда ее включаю.

Кроме хелпера "validator_error", есть еще хелпер "validator_any_error".
  my $errors     = $self->validator_error;         # hashref with errors
  my $pass_error = $self->validator_error('pass'); # password error text
  my $any_error  = $self->validator_any_error;     # any error


На CPAN есть еще один хороший плагин для валидации  - Mojolicious::Plugin::Validator, возможно он придется кому-то больше по душе.

UPD: Описание возможностей Validate::Tiny

11 коммент.:

afiskon комментирует...

Более чем доволен плагином от vti. Он еще подставляет заполненные пользователем поля в случае ошибки и позволяет легко выводить напротив полей с ошибками описание, что было сделано не так. Умеет ли это ваш плагин?

koorchik комментирует...

>Он еще подставляет заполненные пользователем поля в случае ошибки и позволяет легко выводить напротив полей с ошибками описание
Для этого в моем плагине есть аналогичный хелпер - "validator_error".
В контроллере получить текст ошибки можно так:
$self->validator_error('param_name');
в шаблоне так:
<%= validator_error 'param_name' %>

koorchik комментирует...

Описание возможностей Validate::Tiny - http://ifnx.com/articles/2012/1/minimalistic-data-validation.html

Анонимный комментирует...

Хотелось бы валидатор которые воспринимал правила из jquery плагина validate, что бы не дублировать backend и frontend.
Вот думаю написать свой велосипед? Как считаете правильно я мыслю?

koorchik комментирует...

Многие к этому приходят. Если у Вас получится удобный в использовании инструмент - это будет отлично.

Сразу озвучу несколько моментов:
1. На клиент-сайде может использоваться несколько валидаторов. Например, у меня используется jQgrid и его родная валидация.
2. Как быть с многоязычностью сообщений? Например, если сообщение выглядит - lang("username is required"), как это правильно преобразовать в сервер-сайд код?
3. Правила валидации могут содержать ссылки на функции. Как это обрабатывать?

Простое и приемлемое решение для меня - это генератор кода. На входе - правила jquery.validate, а на выходе - правила для какого-нибудь популярного сервер-сайд валидатора (например, в формате Validate::Tiny, или возможно даже в нескольких форматах, на выбор). Полученные правила можно немного отредактировать, добавить поддержку локализации и вставить в основной код.

Либо, можно использовать какой-то свой формат описания правил и генерировать исходя из него правила для Perl валидатора и правила для JS-валидатора.

Сергей Андреев комментирует...

Согласен, вариант с транслятором правил в/из jquery плагины самый оптимальный.

Sergey Malochinskiy комментирует...

Прошу помощи... не могу понять где я неправ.

Подключаю плагин:
$self->plugin('ValidateTiny');

В контроллере добавляю правила:
my $validate_rules = [

# All of these are required
[qw/username password/] => is_required()
];

Все. После этого контроллер ломается:
[Tue Jun 26 21:37:50 2012] [debug] Routing to controller "RCAnswers::Controller::Account" and action "signin".
Use of inherited AUTOLOAD for non-method RCAnswers::Controller::Account::is_required() is deprecated at script/../lib/RCAnswers/Controller/Account.pm line 18.
[Tue Jun 26 21:37:50 2012] [error] Undefined subroutine &RCAnswers::Controller::Account::is_required called at /root/perl5/lib/perl5/Mojolicious/Routes.pm line 143

Не могу понять в чем дело...

koorchik комментирует...

is_required - это функция-шорткат с модуля Validate::Tiny, которая возвращает ссылку на замыкание.

Необходимо добавить "is_required" в импорт:
use Validate::Tiny qw/is_required/;

Sergey Malochinskiy комментирует...

Добавил в контроллер строку use Validate::Tiny qw/is_required/;
Заработало...
Это что же теперь в каждом контроллере где нужна валидация все нужные шорткаты из Validate::Tiny подключать? Я думал это задача плагина все загрузить и предоставить интерфейс...

Это я туплю?

koorchik комментирует...

Либо нужно импортировать шорткаты в контроллер, либо указывать полное название - Validate::Tiny::is_required()

Sergey Malochinskiy комментирует...

Спасибо. Буду указывать полное название.

Отправить комментарий

Не забудьте добавить себя в постоянные читатели и включить уведомления о новых комментариях, либо воспользуйтесь RSS каналом ;)