Skip to content

Instantly share code, notes, and snippets.

/filter.diff Secret

Created August 30, 2014 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/eb7b8ea9ff0e23719dc3 to your computer and use it in GitHub Desktop.
Save anonymous/eb7b8ea9ff0e23719dc3 to your computer and use it in GitHub Desktop.
diff --git a/Changes b/Changes
index 4a459b8..bff1a4f 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
5.18 2014-07-25
+ - Added filters attribute to Mojolicious::Validator.
+ - Added add_filter method to Mojolicious::Validator.
+ - Added filter method to Mojolicious::Validator::Validation.
- Improved is_readable performance in Mojo::Reactor.
5.17 2014-07-24
diff --git a/lib/Mojolicious/Routes.pm b/lib/Mojolicious/Routes.pm
index 82fd6ba..ba9fa6c 100644
--- a/lib/Mojolicious/Routes.pm
+++ b/lib/Mojolicious/Routes.pm
@@ -5,6 +5,7 @@ use List::Util 'first';
use Mojo::Cache;
use Mojo::Loader;
use Mojo::Util 'camelize';
+use Mojolicious::Renderer;
use Mojolicious::Routes::Match;
use Scalar::Util 'weaken';
@@ -14,8 +15,8 @@ has [qw(conditions shortcuts)] => sub { {} };
has hidden => sub { [qw(attr has new tap)] };
has namespaces => sub { [] };
-sub add_condition { shift->_add(conditions => @_) }
-sub add_shortcut { shift->_add(shortcuts => @_) }
+sub add_condition { shift->Mojolicious::Renderer::_add(conditions => @_) }
+sub add_shortcut { shift->Mojolicious::Renderer::_add(shortcuts => @_) }
sub auto_render {
my ($self, $c) = @_;
@@ -106,12 +107,6 @@ sub route {
sub _action { shift->plugins->emit_chain(around_action => @_) }
-sub _add {
- my ($self, $attr, $name, $cb) = @_;
- $self->$attr->{$name} = $cb;
- return $self;
-}
-
sub _callback {
my ($self, $c, $cb, $last) = @_;
$c->stash->{'mojo.routed'}++ if $last;
diff --git a/lib/Mojolicious/Validator.pm b/lib/Mojolicious/Validator.pm
index 6d5f291..2fba803 100644
--- a/lib/Mojolicious/Validator.pm
+++ b/lib/Mojolicious/Validator.pm
@@ -1,17 +1,17 @@
package Mojolicious::Validator;
use Mojo::Base -base;
+use Mojo::Util 'trim';
+use Mojolicious::Renderer;
use Mojolicious::Validator::Validation;
has checks => sub {
{equal_to => \&_equal_to, in => \&_in, like => \&_like, size => \&_size};
};
+has filters => sub { {trim => \&_trim} };
-sub add_check {
- my ($self, $name, $cb) = @_;
- $self->checks->{$name} = $cb;
- return $self;
-}
+sub add_check { shift->Mojolicious::Renderer::_add(checks => @_) }
+sub add_filter { shift->Mojolicious::Renderer::_add(filters => @_) }
sub validation {
Mojolicious::Validator::Validation->new(validator => shift);
@@ -37,6 +37,8 @@ sub _size {
return $len < $min || $len > $max;
}
+sub _trim { trim $_[1] }
+
1;
=encoding utf8
@@ -87,6 +89,16 @@ Value needs to match the regular expression.
Value length in characters needs to be between these two values.
+=head1 FILTERS
+
+These filters are available by default.
+
+=head2 trim
+
+ $validation->filter('trim');
+
+Trim whitespace characters from both ends of value.
+
=head1 ATTRIBUTES
L<Mojolicious::Validator> implements the following attributes.
@@ -99,6 +111,13 @@ L<Mojolicious::Validator> implements the following attribute
Registered validation checks, by default only L</"equal_to">, L</"in">,
L</"like"> and L</"size"> are already defined.
+=head2 filters
+
+ my $filters = $validator->filters;
+ $validator = $validator->filters({trim => sub {...}});
+
+Registered filters, by default only L</"trim"> is already defined.
+
=head1 METHODS
L<Mojolicious::Validator> inherits all methods from L<Mojo::Base> and
@@ -110,6 +129,12 @@ implements the following new ones.
Register a new validation check.
+=head2 add_filter
+
+ $validator = $validator->add_filter(trim => sub {...});
+
+Register a new filter.
+
=head2 validation
my $validation = $validator->validation;
diff --git a/lib/Mojolicious/Validator/Validation.pm b/lib/Mojolicious/Validator
index 56f291c..30742ec 100644
--- a/lib/Mojolicious/Validator/Validation.pm
+++ b/lib/Mojolicious/Validator/Validation.pm
@@ -54,6 +54,22 @@ sub error {
return $self;
}
+sub filter {
+ my ($self, $filter) = (shift, shift);
+
+ return $self unless my $cb = $self->validator->filters->{$filter};
+ return $self unless defined(my $name = $self->topic);
+ my $output = $self->output;
+ return $self unless defined(my $value = $output->{$name});
+
+ $self->input->{$name} = $output->{$name}
+ = ref $value eq 'ARRAY'
+ ? [map { $self->$cb($_, @_) } @$value]
+ : $self->$cb($value, @_);
+
+ return $self;
+}
+
sub has_data { !!keys %{shift->input} }
sub has_error { $_[1] ? exists $_[0]{error}{$_[1]} : !!keys %{$_[0]{error}} }
@@ -184,6 +200,12 @@ only be one per field.
my ($check, $result, @args) = @{$validation->error('foo')};
+=head2 filter
+
+ $validation = $validation->filter('trim');
+
+Filter all values of the current L</"topic">.
+
=head2 has_data
my $bool = $validation->has_data;
diff --git a/t/mojolicious/validation_lite_app.t b/t/mojolicious/validation_lite
index e8f3c25..9e2b7a2 100644
--- a/t/mojolicious/validation_lite_app.t
+++ b/t/mojolicious/validation_lite_app.t
@@ -113,6 +113,16 @@ is_deeply $validation->output, {foo => 'bar'}, 'right resul
ok $validation->has_error, 'has error';
is_deeply $validation->error('yada'), [qw(size 1 5 10)], 'right error';
+# Trim
+$validation = $t->app->validation->input({foo => ' bar', baz => [' 0 ', 1]});
+ok $validation->required('foo')->filter('trim')->in('bar')->is_valid, 'valid';
+is_deeply $validation->output, {foo => 'bar'}, 'right result';
+ok $validation->optional('baz')->filter('trim')->like(qr/\d/)->is_valid,
+ 'valid';
+is_deeply $validation->output, {foo => 'bar', baz => [0, 1]}, 'right result';
+ok !$validation->in(23)->filter('trim')->is_valid, 'not valid';
+is_deeply $validation->output, {foo => 'bar'}, 'right result';
+
# Multiple empty values
$validation = $t->app->validation;
ok !$validation->has_data, 'no data';
@@ -130,6 +140,17 @@ ok $validation->required('0')->size(1, 1)->is_valid, 'valid
is_deeply $validation->output, {0 => 0}, 'right result';
is $validation->param('0'), 0, 'right value';
+# Custom filter
+$t->app->validator->add_filter(wrap => sub { join '', @_[2, 1, 3] });
+$validation = $t->app->validation->input({foo => [' bar', 'baz'], yada => 3});
+ok $validation->required('foo')->filter('wrap', 'a', 'b')->like(qr/^a.+b$/)
+ ->is_valid, 'valid';
+is_deeply $validation->output, {foo => ['a barb', 'abazb']}, 'right result';
+ok $validation->optional('yada')->filter('wrap', '3', '4')->in('334')
+ ->is_valid, 'valid';
+is_deeply $validation->output, {foo => ['a barb', 'abazb'], yada => 334},
+ 'right result';
+
# Custom error
$validation = $t->app->validation->input({foo => 'bar'});
ok !$validation->required('foo')->has_error, 'no error';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment