Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
removed generators for dynamic error messages from Mojolicious::Valid…
…ator
  • Loading branch information
kraih committed Oct 2, 2013
1 parent 307d6e1 commit f84d17f
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 119 deletions.
1 change: 1 addition & 0 deletions Changes
@@ -1,5 +1,6 @@

4.43 2013-10-02
- Removed generators for dynamic error messages from Mojolicious::Validator.

4.42 2013-09-30
- Added EXPERIMENTAL form validation support.
Expand Down
19 changes: 7 additions & 12 deletions lib/Mojolicious/Guides/Rendering.pod
Expand Up @@ -690,10 +690,8 @@ L<Mojolicious::Validator/"CHECKS">.

=head2 Adding form validation checks

There are two parts to every validation check, the check itself, returning
true or false, and an optional generator for dynamic error messages. Both look
very similar and can be registered with L<Mojolicious::Validator/"add_check">
and L<Mojolicious::Validator/"add_error">.
Validation checks only have to return true or false and can be registered with
L<Mojolicious::Validator/"add_check">.

use Mojolicious::Lite;

Expand All @@ -703,12 +701,6 @@ and L<Mojolicious::Validator/"add_error">.
return $value >= $min && $value <= $max;
});

# Add "range" error generator
app->validator->add_error(range => sub {
my ($validation, $name, $value, $min, $max) = @_;
return "Value needs to be between $min and $max.";
});

get '/' => 'form';

post '/test' => sub {
Expand Down Expand Up @@ -737,8 +729,11 @@ and L<Mojolicious::Validator/"add_error">.
<p>Thanks, the number <%= $number %> was valid.</p>
% }
%= form_for test => begin
% if (validation->has_error('number')) {
<p><%= validation->errors('number') %></p>
% if (my $err = validation->error('number')) {
<p>
%= 'Value is required.' if $err->[0] eq 'required'
%= 'Value needs to be between 3 and 23.' if $err->[0] eq 'range'
</p>
% }
%= text_field 'number'
%= submit_button
Expand Down
36 changes: 6 additions & 30 deletions lib/Mojolicious/Validator.pm
Expand Up @@ -6,28 +6,18 @@ use Mojolicious::Validator::Validation;
has checks => sub {
{equal_to => \&_equal_to, in => \&_in, regex => \&_regex, size => \&_size};
};
has errors => sub {
{
equal_to => sub {'Values are not equal.'},
in => sub {'Value is not allowed.'},
required => sub {'Value is required.'},
size => sub {qq{Value needs to be $_[3]-$_[4] characters long.}}
};
};

sub add_check { shift->_add(checks => @_) }
sub add_error { shift->_add(errors => @_) }
sub add_check {
my ($self, $name, $cb) = @_;
$self->checks->{$name} = $cb;
return $self;
}


sub validation {
Mojolicious::Validator::Validation->new(validator => shift);
}

sub _add {
my ($self, $attr, $name, $cb) = @_;
$self->$attr->{$name} = $cb;
return $self;
}

sub _equal_to {
my ($validation, $name, $value, $to) = @_;
return undef unless defined(my $other = $validation->input->{$to});
Expand Down Expand Up @@ -108,14 +98,6 @@ L<Mojolicious::Validator> implements the following attributes.
Registered validation checks, by default only C<equal_to>, C<in>, C<regex> and
C<size> are already defined.
=head2 errors
my $errors = $validator->errors;
$validator = $validator->errors({size => sub {...}});
Registered generators for dynamic error messages, by default only C<equal_to>,
C<in>, C<required> and C<size> are already defined.
=head1 METHODS
L<Mojolicious::Validator> inherits all methods from L<Mojo::Base> and
Expand All @@ -127,12 +109,6 @@ implements the following new ones.
Register a new validation check.
=head2 add_error
$validator = $validator->add_error(size => sub {...});
Register a new generator for dynamic error messages.
=head2 validation
my $validation = $validator->validation;
Expand Down
36 changes: 5 additions & 31 deletions lib/Mojolicious/Validator/Validation.pm
Expand Up @@ -3,7 +3,6 @@ use Mojo::Base -base;

use Carp 'croak';
use Scalar::Util 'blessed';
use Mojo::Collection;

has [qw(input output)] => sub { {} };
has [qw(topic validator)];
Expand All @@ -25,7 +24,6 @@ sub DESTROY { }
sub check {
my ($self, $check) = (shift, shift);

my $err = delete $self->{error};
return $self unless $self->is_valid;

my $cb = $self->validator->checks->{$check};
Expand All @@ -34,20 +32,14 @@ sub check {
for my $value (ref $input eq 'ARRAY' ? @$input : $input) {
next if $self->$cb($name, $value, @_);
delete $self->output->{$name};
$self->_error($check, $err, $name, $value, @_);
$self->{errors}{$name} = [$check, $value, @_];
last;
}

return $self;
}

sub error {
my $self = shift;
$self->{error} = shift;
return $self;
}

sub errors { Mojo::Collection->new(@{shift->{errors}{shift()} // []}) }
sub error { shift->{errors}{shift()} }

sub has_data { !!keys %{shift->input} }

Expand Down Expand Up @@ -83,18 +75,10 @@ sub param {
sub required {
my ($self, $name) = @_;
$self->optional($name);
my $err = delete $self->{error};
$self->_error('required', $err, $name) unless $self->is_valid;
$self->{errors}{$name} = ['required'] unless $self->is_valid;
return $self;
}

sub _error {
my ($self, $check, $err, $name, $value)
= (shift, shift, shift, shift, shift);
my $cb = $self->validator->errors->{$check} // sub {'Value is not valid.'};
push @{$self->{errors}{$name}}, $err // $self->$cb($name, $value, @_);
}

1;

=encoding utf8
Expand Down Expand Up @@ -162,19 +146,9 @@ Perform validation check.
=head2 error
$validation = $validation->error('This went wrong.');
Set custom error message for next validation C<check> or C<topic> change.
$validation->optional('name')
->error('Name needs to be between 3 and 9 characters long.')->size(3, 9);
=head2 errors
my $collection = $validation->errors('foo');
my $err = $validation->error('foo');
Return L<Mojo::Collection> object containing all error messages for failed
validation checks.
Return details about failed validation check.
=head2 has_data
Expand Down
60 changes: 14 additions & 46 deletions t/mojolicious/validation_lite_app.t
Expand Up @@ -11,7 +11,6 @@ use Test::Mojo;

# Custom check
app->validator->add_check(two => sub { length $_[2] == 2 });
app->validator->add_error(two => sub {'My error.'});

get '/' => sub {
my $self = shift;
Expand Down Expand Up @@ -47,8 +46,7 @@ ok !$validation->has_error, 'no error';
ok !$validation->required('does_not_exist')->is_valid, 'not valid';
is_deeply $validation->output, {foo => 'bar', baz => 'yada'}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('does_not_exist')->each],
['Value is required.'], 'right error';
is_deeply $validation->error('does_not_exist'), ['required'], 'right error';

# Equal to
$validation = $t->app->validation;
Expand All @@ -60,12 +58,12 @@ ok !$validation->optional('baz')->equal_to('does_not_exist')->is_valid,
'not valid';
is_deeply $validation->output, {foo => 'bar'}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('baz')->each], ['Values are not equal.'],
is_deeply $validation->error('baz'), ['equal_to', 'bar', 'does_not_exist'],
'right error';
ok !$validation->optional('yada')->equal_to('foo')->is_valid, 'not valid';
is_deeply $validation->output, {foo => 'bar'}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('yada')->each], ['Values are not equal.'],
is_deeply $validation->error('yada'), ['equal_to', 'yada', 'foo'],
'right error';

# In
Expand All @@ -77,7 +75,7 @@ ok !$validation->has_error, 'no error';
ok !$validation->required('baz')->in(qw(yada whatever))->is_valid, 'not valid';
is_deeply $validation->output, {foo => [qw(bar whatever)]}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('baz')->each], ['Value is not allowed.'],
is_deeply $validation->error('baz'), [qw(in ohoh yada whatever)],
'right error';

# Regex
Expand All @@ -86,11 +84,11 @@ $validation->input({foo => 'bar', baz => 'yada'});
ok $validation->required('foo')->regex(qr/^b/)->is_valid, 'valid';
is_deeply $validation->output, {foo => 'bar'}, 'right result';
ok !$validation->has_error, 'no error';
ok !$validation->required('baz')->regex(qr/ar$/)->is_valid, 'not valid';
my $re = qr/ar$/;
ok !$validation->required('baz')->regex($re)->is_valid, 'not valid';
is_deeply $validation->output, {foo => 'bar'}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('baz')->each], ['Value is not valid.'],
'right error';
is_deeply $validation->error('baz'), [qw(regex yada), $re], 'right error';

# Size
$validation = $t->app->validation;
Expand All @@ -101,41 +99,12 @@ ok !$validation->has_error, 'no error';
ok !$validation->required('baz')->size(1, 3)->is_valid, 'not valid';
is_deeply $validation->output, {foo => 'bar'}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('baz')->each],
['Value needs to be 1-3 characters long.'], 'right error';
is_deeply $validation->error('baz'), [qw(size yada 1 3)], 'right error';
ok !$validation->required('yada')->size(5, 10)->is_valid, 'not valid';
is $validation->topic, 'yada', 'right topic';
is_deeply $validation->output, {foo => 'bar'}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('yada')->each],
['Value needs to be 5-10 characters long.'], 'right error';

# Custom errors
$validation = $t->app->validation;
ok !$validation->has_error('bar'), 'no error';
$validation->input({foo => 'bar', yada => 'yada'});
ok !$validation->error('Bar is required.')->required('bar')->is_valid,
'not valid';
is_deeply $validation->output, {}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('bar')->each], ['Bar is required.'],
'right error';
ok !$validation->required('baz')->is_valid, 'not valid';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('baz')->each], ['Value is required.'],
'right error';
ok !$validation->required('foo')->error('Foo is too small.')->size(25, 100)
->is_valid, 'not valid';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('foo')->each], ['Foo is too small.'],
'right error';
is $validation->topic, 'foo', 'right topic';
ok !$validation->error('Failed!')->required('yada')->size(25, 100)->is_valid,
'not valid';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('yada')->each],
['Value needs to be 25-100 characters long.'], 'right error';
is $validation->topic, 'yada', 'right topic';
ok $validation->has_error('bar'), 'has error';
is_deeply $validation->error('yada'), [qw(size yada 5 10)], 'right error';

# Multiple empty values
$validation = $t->app->validation;
Expand All @@ -145,8 +114,7 @@ ok $validation->has_data, 'has data';
ok !$validation->required('foo')->is_valid, 'not valid';
is_deeply $validation->output, {}, 'right result';
ok $validation->has_error, 'has error';
is_deeply [$validation->errors('foo')->each], ['Value is required.'],
'right error';
is_deeply $validation->error('foo'), ['required'], 'right error';

# Missing method and function (AUTOLOAD)
eval { $t->app->validation->missing };
Expand All @@ -172,7 +140,7 @@ $t->get_ok('/' => form => {foo => '☃☃'})->status_is(200)

# Validation failed for required fields
$t->get_ok('/' => form => {foo => 'no'})->status_is(200)
->text_is('div:root' => 'Value is not allowed.')
->text_is('div:root' => 'in')
->text_is('label.custom.field-with-error[for="foo"]' => '<Foo>')
->element_exists('input.custom.field-with-error[type="text"][value="no"]')
->element_exists_not('textarea.field-with-error')
Expand All @@ -182,7 +150,7 @@ $t->get_ok('/' => form => {foo => 'no'})->status_is(200)

# Failed validation for all fields
$t->get_ok('/?foo=too_long&bar=too_long_too&baz=way_too_long&yada=whatever')
->status_is(200)->text_is('div:root' => 'My error.')
->status_is(200)->text_is('div:root' => 'two')
->text_is('label.custom.field-with-error[for="foo"]' => '<Foo>')
->element_exists('input.custom.field-with-error[type="text"]')
->element_exists('textarea.field-with-error')
Expand All @@ -196,7 +164,7 @@ __DATA__
@@ index.html.ep
% if (validation->has_error('foo')) {
<div><%= validation->errors('foo') %></div>
<div><%= validation->error('foo')->[0] %></div>
% }
%= form_for index => begin
%= label_for foo => '<Foo>', class => 'custom'
Expand Down

0 comments on commit f84d17f

Please sign in to comment.