I'm looking for namespace and package name suggestions for a (yes,
another) form processing module.
Its job it to move data between a store and input/output forms,
validating along the way. It doesn't generate any HTML, although I use
it in web applications mostly. But it's not limited to web
applications.
In my world it's in the "Form" namespace (Form::Base, Form::Field,
Form::Model). But I'm not sure where it fits best in CPAN.
Here's a somewhat brief description:
A user of this module creates a form object that is used in their
application. The user's form object inherits from this module (currently
called Form::Base). A form is made up of field objects that inherit
from Form::Field. So A "Text" field is Form::Field::Text and inherits
from Form::Field. An "Integer" field is Form::Field::Integer and
inherits from Form::Field::Text. And so on.
Fields can contain a form object, so compound fields are easy to
build (such as separate day, month, year that is a DateTime object
internally).
The magic of this module is when forms inherit from a "model" class
instead of directly from Form::Base. For example, I use Class::DBI
and there's Form::Model::CDBI. By looking at the database
relationships Form::Model::CDBI can populate option lists, validate
against those lists, and update many-to-many relationships.
The module is based partly on the design of Rose-HTML-Objects, but
again, this module focuses more on the database side instead of doing
HTML generation.
Here's a synopsis, if still following along:
In an application you might want a controller to handle creating and
updating a "User"
record. And not want to write much code. Here's using Catalyst as an
example:
# Catalyst Controller
package MyApplication::Controller::User;
use strict;
use MyApplication::Form::User;
sub edit : Local {
my ( $self, $c, $id ) = @_;
# Create the form object
my $form = MyApplication::Form::User->new( $id );
# Update the user record if form posted and form validates
$form->update_from_from( $c->request->parameters )
if $c->form_posted;
$c->stash->{form} = $form;
}
The above form class might then look like this:
package MyApplication::Form::User;
use strict;
use base 'Form::Model::CDBI';
sub object_class { 'DB::User' }
sub profile {
my $self = shift;
return {
required => {
name => 'Text',
age => 'PosInteger',
username => 'Text'.
password => 'Password',
sex => 'Select',
birthdate => 'PastDate',
},
optional => {
hobbies => 'Multiple', # many-to-many
address => 'Text',
city => 'Text',
state => 'Select', # lookup table
},
# Make sure this is unique in the database
unique => [ qw/ username / ],
# if any entered then all are required
dependency => [
[qw/ address city state /],
],
};
}
sub options_sex {
return (
m => 'Male',
f => 'Female',
);
}
sub validate_age {
my ( $self, $field ) = @_;
$field->add_error('Sorry, you must be 18')
if $field->value < 18;
}
Or when you need a quick, small form do this in a controller:
my @fields = qw/ first_name last_name email /;
$c->stash->{form} = Form::Base->new(
profile => {
required => {
map { $_ => 'Text' } qw/ first_name last_name email /,
},
},
);
--
Bill Moseley
[EMAIL PROTECTED]