Snippets

Brian Medley Example filter implementation

Created by Brian Medley
package Mojolicious::Validator::Validation;
use Mojo::Base -base;

use Carp         ();
use Scalar::Util ();

has [qw(csrf_token topic validator)];
has [qw(input output)] => sub { {} };

sub AUTOLOAD {
  my $self = shift;

#   $DB::single = 1;

  my ($package, $method) = our $AUTOLOAD =~ /^(.+)::(.+)$/;
  Carp::croak "Undefined subroutine &${package}::$method called"
    unless Scalar::Util::blessed $self && $self->isa(__PACKAGE__);

  Carp::croak "Namspace collision: $method for checks and filters" 
    if $self->validator->checks->{$method} && $self->validator->filter->{$method};

  return $self->check($method => @_) if $self->validator->checks->{$method};
  return $self->filter($method => @_) if $self->validator->filter->{$method};
  Carp::croak qq{Can't locate object method "$method" via package "$package"};
}

# ...

sub filter {
  my ($self, $filter) = (shift, shift);

  my $cb    = $self->validator->filter->{$filter};
  my $name  = $self->topic;
  my $input = $self->input->{$name};
  for my $value (ref $input eq 'ARRAY' ? @$input : $input) {
    next unless my $result = $self->$cb($name, $value, @_);
    return $self->error($name => [$filter, $result, @_]);
  }

  return $self;
}

# ...
package Mojolicious::Validator;
use Mojo::Base -base;

use Mojolicious::Validator::Validation;

has checks => sub {
  {equal_to => \&_equal_to, in => \&_in, like => \&_like, size => \&_size};
};

has filter => sub {
  {lc => \&_lc, uc => \&_uc};
};

# ...

sub _like { $_[2] !~ $_[3] }

sub _size {
  my ($validation, $name, $value, $min, $max) = @_;
  warn($name, " :: ", $value);
  my $len = length $value;
  return $len < $min || $len > $max;
}

sub _lc {
  my ($validation, $name, $value) = @_;
  $validation->input->{$name} = lc($value);
  return 0;
}

sub _uc {
  my ($validation, $name, $value) = @_;
  $validation->input->{$name} = uc($value);
  return 0;
}

1;
use Mojolicious::Lite;

get '/' => sub {
  my $c = shift;

  # Check if parameters have been submitted
  my $validation = $c->validation;
  return $c->render unless $validation->has_data;

  # Validate parameters ("pass_again" depends on "pass")
  $validation->required('user')->uc->size(1, 20)->like(qr/^[E-T]+$/);
  $validation->required('pass_again')->lc->equal_to('pass')
    if $validation->optional('pass')->lc->size(7, 500)->is_valid;

  # Render confirmation if validation was successful
  $c->render('thanks') unless $validation->has_error;
} => 'index';

app->start;

__DATA__

@@ index.html.ep
<!DOCTYPE html>
<html>
  <head>
    <style>
      label.field-with-error { color: #dd7e5e }
      input.field-with-error { background-color: #fd9e7e }
      password.field-with-error { background-color: #fd9e7e }
    </style>
  </head>
  <body>
    %= form_for index => begin
      %= label_for user => 'Username (required, 1-20 characters, only e-t)'
      <br>
      %= text_field 'user'
      %= submit_button
      <br>
      %= label_for pass => 'Password (optional, 7-500 characters)'
      <br>
      %= password_field 'pass'
      <br>
      %= label_for pass_again => 'Password again (equal to the value above)'
      <br>
      %= password_field 'pass_again'
    % end
  </body>
</html>

@@ thanks.html.ep
<!DOCTYPE html>
<html><body>Thank you <%= validation->param('user') %>.</body></html>

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.