Search code examples
perldancer

simple form validation in dancer/perl


I am trying to do a simple form validation in perl dancer but I was wondering what would be the best way to validate simple parameters (e.g. field cannot be empty, validity of the email, minimum length of a field) in dancer/perl without any extra plugin or CPAN module

here is the code so far

post '/register' => sub {

my $db = connect_db();
my $sql = 'insert into users (username, email, password, motivation) values (?, ?, ? ,?)';
my $sth = $db->prepare($sql) or die $db->errstr;
$sth->execute(params->{'username'}, params->{'email'},params->{'password'}, params->{'motivation'}) or die $sth->errstr;

set_flash('Hey you signed up !');
redirect '/thanks';
};

I did google it and I found several ways to do validation using CPAN modules like Form::Foo but how do it without that ?


Solution

  • I'm not sure why you'd want to expressly avoid using a plugin or a CPAN module - any solution you come up with will likely do the the same things as a plugin and/or CPAN module except that since it's new code it won't be as mature and tested.

    I've recently started using Dancer to develop a simple app and I'll describe how I'm solving this problem using CPAN modules. You may of course choose to ignore it.

    My route handler for adding a user looks like this:

    post '/user/add' => {
        my $args = valid_input('/user/add')
            or return template('user/add');
        my $user = User->new({
            username => $args->{username},
            # ...
        });
        user->insert;  # you'll probably want some error handling here
        set_flash('User added');
        redirect '/user';
    };
    

    The valid_input function is a helper I created for my app, which uses the Data::Form::Validator module from CPAN. The '/usr/add' argument is the name of the validation profile to use - which for simplicity I decided to keep the same as the route name.

    I won't bore you with the details of calling Data::Form::Validator since the documentation is pretty good. What I will mention is that in the event that validation fails, the valid_input helper stores away the validation error messages for display in an alert box and also saves the submitted parameters:

    my $q = params();  # need to force scalar context to get a hashref;
    fill_in_form($q);  # save submitted parameters
    

    I have a before_template_render hook that makes the saved validation error messages available to the template (they actually get rendered in views/layouts/main.tt).

    I also have an after_template_render hook that takes the saved submitted parameters and puts them back into the rendered HTML form using the HTML::FillInForm module.

    Since I have that infrastructure in place, the route handler to display an existing user record in an edit form with all the fields pre-populated is trivial:

    get '/user/:id' => sub {
        if( my $user = User->find( param('id') ) ) {
            fill_in_form($user);
            return template 'user/edit', { id => $user->id };
        }
        not_found "User not found";
    };
    

    The User in User->find() is another one of my app-specific helper functions. It uses the Dancer::Plugin::DBIC module to return a resultset object for my user table.

    I will say that I'm not necessarily a huge fan of Data::Form::Validator. I have been able to achieve everything I wanted but sometimes it does seem to take more work than I'd like.