[Catalyst] Making Controllers thin and Models thick

Bill Moseley moseley at hank.org
Wed Jul 18 13:07:29 GMT 2007


On Wed, Jul 18, 2007 at 09:39:25AM +0000, Zbigniew Lukasiak wrote:
> Hi there,
> 
> I am too working on a thick model component.  It's a ResultSet base
> class with functions bearing (provisional?) names: build_create and
> build_update.  They do params validation and update the database in a
> transaction with data for both the individual record and related
> stuff.

Sounds like both you and Ken are pushing the validation into the
model -- or rather the ORM layer.  The model needs to do some
validation, of course, and I like to push that into the RDBMS where
possible.

I do wonder if that's not coupling the ORM and the validation too
closely.  Not that it happens very often, but if you decided to change
ORMs you would would still want the same validation of input data.

I tend to have a separate layer between the controller and the model
for validation.

> In short the CRUD controller actions using it can be as simple as:
> 
> sub update : Local {
>    my ( $self, $c, $id ) = @_;
>    if ( $c->request->method eq 'POST' ){
>        my $update_result = $c->model( 'DB::Table' )->build_update(
> $id, $c->request->params() );
>        if ( $update_result->{status} eq 'OK' ){
>            $c->res->redirect( $c->uri_for( "table/view", $id") );
>        }else{
>            $c->stash( update_result => $update_result );
>       }
>    }else{
>        $c->stash( item => $c->model( 'DB::Table' )->find( $id ) );
>    }
> }


I suspect you write that enough times and you will notice the common
code.

My Create/Update controllers tend to look like this:

    sub edit : Local {
        my ( $self, $c, $id ) = @_;

        $c->post_redirect( 'list', 'Foo was updated' )
            if $c->update_from_from( $id );

    }

Because update_from_form knows the action path and can therefore find
the associated form.  It can also determine what the concept of a
posted form is in a single place.  And the associated form knows what
model class to update or create a row in.  And the model class knows
how to validate ids.  And the form knows how to look at the model
class and determine lookup values for one-to-many and many-to-many
relationships.

I might validate $id a bit more to make sure the current user can
access it, but that can also happen in a chain or auto method.  Or
that might be considered part of the validation and the form module
can validate that the user can access $id.  But, I kind of consider
that more of a controller responsibility since an invalid $id in the
path for a given user is an invalid path (and thus maybe a 404).

-- 
Bill Moseley
moseley at hank.org




More information about the Catalyst mailing list