[Catalyst] Putting more in the View
Bill Moseley
moseley at hank.org
Thu Feb 16 17:32:43 CET 2006
On Thu, Feb 16, 2006 at 11:19:08AM +0000, Ian Docherty wrote:
>
> FormValidator will help me to make my form validation code cleaner. (I
> still need to research this more).
I know lots of people use FormValidator, but I got really tired
fighting with it. Take a look at the other options available before
making a decision. Specifically, take a look at Rose::HTML::Objects
and see if that fits with your thinking.
> I gather that you are doing the database insert and update (via ORM) in
> your Form class? I can't decide if this is good or bad. It hides some of
> the business logic in a class and it is not so easy to see the logic in
> the controller.
I don't agree. The form object is an interface that knows how to
convert data from its internal format to a format used for user I/O
(which in my case with HTML forms is simply a hash). Obviously,
validation has to be part of that process. If a field is a date then
it should be a valid date. If the field is a login name then it must
be unique (which means checking the database). If it's a select then
it must be a valid value, and those valid values may (or may not)
have come from the database via relationships.
The controller's job, on the other hand, is to update, say, a user's
profile. The controller doesn't really need to know what specific
fields to update -- it just needs to display the form, and then pass
the request parameters to the form and know if anything is updated.
Yes, it's hiding complexity.
> However I like the idea of simplifying the Controller. That is what I
> was aiming towards. What you do however is to hide much of the
> complexity in the Form class (which is no bad thing). However much of
> the complexity still remains.
But that complexity is the same for all my forms, so instead of
having it in all my controllers it's all in one place.
> One final request. It would help me greatly if I could see an example of
> your WS2::Form::Admin::Person class. I am still unsure how you have
> implemented it (as a Plugin for example, or how you have implemented the
> $c->form_posted method).
package WS2::Form::Admin::Person;
use strict;
use warnings;
use base 'Form::Model::CDBI';
sub object_class { 'DB::Person' }
sub profile {
my ( $self ) = @_;
my $profile = {
required => {
first_name => 'Text',
last_name => 'Text',
email => 'Email',
login => 'Text',
status => 'Select',
roles => 'Multiple',
},
optional => {
url => 'Text',
bio => 'HtmlArea',
phone => 'Text',
address1 => 'Text',
address2 => 'Text',
city => 'Text',
state => 'Select',
zip => 'USZipcode',
bill_office => 'Text',
bill_attention => 'Text',
bill_address1 => 'Text',
bill_address2 => 'Text',
bill_city => 'Text',
bill_state => 'Select',
bill_zip => 'USZipcode',
bill_phone => 'Text',
time_zone => 'Select',
password => 'Password',
password_chk => 'Password',
organizations => 'Multiple', # A person can belong to many organizations
},
dependency => [
[qw/ password password_chk / ],
[qw/ address1 city state zip /],
[qw/ bill_address1 bill_city bill_state bill_zip /],
],
# login must be unique in the database
unique => [qw/ login /],
};
}
sub init {
my $self = shift;
my $return = $self->SUPER::init(@_);
# on a new person, require password
unless ($self->item) {
$self->field($_)->required(1) for qw/ password password_chk /;
}
return $return;
}
sub validate_password_chk {
my ( $self, $field ) = @_;
$field->add_error('Passwords do not match')
unless $field->value eq $self->field('password')->value;
$field->add_error('Password must be different from old password')
if $field->value eq $self->field('old_password')->value;
}
sub cross_validate {
my $self = shift;
my $pf = $self->field('password');
# Tell Model::CDBI to not update the password field unless
# it's entered.
$pf->noupdate(1) unless $pf->value;
}
1;
--
Bill Moseley
moseley at hank.org
More information about the Catalyst
mailing list