Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which Perl module should I use to generate a validating CRUD webform?

Has anyone successfully used something like DBIx::Class::WebForm or CatalystX-CRUD to automagically build a self-validating webform from a database table?

I'm imagining a module that reads a database table schema, reads the constraints for each column, and generates some abstract representation of a webform, with fields for error messages, etc. I'm using Catalyst and Plack with a big existing codebase.

I don't want to code up an HTML webform, nor any validation logic. I'm aiming to write as little code as possible, in the style of Ruby on Rails. Which Perl module is best for this?

UPDATE: I've solved the webform side with HTML::FormFu, but it's still clunky mapping the form inputs onto the database, e.g. date_start and date_end both relate to the 'created' column, and comment should match using 'LIKE %foo%', etc. Where's the 'DBICFu'?

UPDATE: This is for a web application, the webform should not look like a database table. I'm not looking for a database management tool.

like image 871
Will Sheppard Avatar asked Feb 29 '12 10:02

Will Sheppard


3 Answers

You can use use HTML::FormHandler::Moose and HTML::FormHandler::Model::DBIC and get some nice forms.

As a simple example:

The form definition:

package MyStats::Form::Datetime ;

use HTML::FormHandler::Moose ;
extends 'HTML::FormHandler::Model::DBIC' ;

use Date::Calc qw(Today_and_Now) ;

has_field 'datetimeid' => ( label     => 'ID' ) ;
has_field 'datetime'   => ( type      => 'Text',
                            apply     => [ { transform => \&transform_dt } ] ,
                            deflation => \&deflation_dt ,
                            required  => 1 ) ;
has_field 'submit'     => ( type => 'Submit' ,
                            value => 'Speichern' ) ;
# These are the fields of the table datetime

sub transform_dt {
  my ( $dt ) = @_ ;

  my @d = ( $dt =~ m/(\d{1,2})\.(\d{1,2})\.(\d{4})\s+(\d{1,2}):(\d{1,2})/ ) ;
  return sprintf( '%04d-%02d-%02d %02d:%02d:00' , @d[2,1,0,3,4] ) ;
}

sub deflation_dt {
  my ( $dt ) = @_ ;

  my @d = ( $dt =~ m/(\d{4})-(\d{2})-(\d{2})\s+(\d{1,2}):(\d{1,2})/ ) ;
  if( ! @d ) {
    @d = Today_and_Now() ;
  }
  return sprintf( '%02d.%02d.%04d %02d:%02d:00' , @d[2,1,0,3,4] ) ;
}

1 ;

And the usage in a controller:

package MyStats::Controller::Datetime ;
use Moose ;
use namespace::autoclean ;

BEGIN { extends 'Catalyst::Controller' ; }

use MyStats::Form::Datetime ;

has 'form' => ( isa     => 'MyStats::Form::Datetime' ,
                is      => 'rw' ,
                lazy    => 1 ,
                default => \&new_datetime_form ) ;

sub new_datetime_form {
  MyStats::Form::Datetime->new( css_class => 'datetimeform' ,
                                name => 'datetimeform' ) ;
}

...

sub add :Local :Args(0) {
  my ( $self , $ctx ) = @_ ;

  my $data = $ctx->model( 'MyStatsDB::Datetime' )->new_result( {} ) ;
  $ctx->stash( template => 'datetime/add.tt2' ,
               form     => $self->form ) ;
  $ctx->bread_crumb( { name => 'Datum/Zeit eingeben' ,
                       location => '/datetime/add' } ) ;

  $ctx->req->param( 'datetimeid' , undef ) if $ctx->req->param( 'datetimeid' ) ;
  return unless $self->form->process( item   => $data ,
                                      params => $ctx->req->params ) ;
  $ctx->flash( message => 'Neuer Datensatz ' . $data->datetimeid .
                          ' angelegt.' ,
               id_add  => $data->datetimeid ) ;
  $ctx->res->redirect( $ctx->uri_for( '/datetime' ) ) ;
}

...

__PACKAGE__->meta->make_immutable ;

1 ;

Works good.

like image 123
dgw Avatar answered Nov 17 '22 07:11

dgw


I've used HTML::FormHandler to generate forms for me in this fashion. It needs some tweaking, but it does 90% of the work for you. Separately DBIx::Class offers a similar tool.

like image 27
Richard Huxton Avatar answered Nov 17 '22 07:11

Richard Huxton


There are a number of crud options on the Catalyst wiki.

It sounds like AutoCrud would fit your needs.

like image 2
Quentin Avatar answered Nov 17 '22 06:11

Quentin