From time to time the talk about cross cutting Catalyst components is recurring on the mailing list. This is hard - but the basis libraries are improving - so I am sure at some point we'll have them. I believe the way to reach this is by writing examples of functionality that could become such a component - and continuously refining it. Perhaps moving parts to libraries. Enough introduction - let's start the example.

This is a comment system using DBIx::Class and HTML::FormHandler:


First the DBIC definition:

package DBSchema::Comment;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components(qw/TimeStamp PK::Auto Core/);
__PACKAGE__->table('comment');
__PACKAGE__->add_columns(
  id =>  { data_type => 'integer', is_auto_increment => 1, is_nullable => 0 },
  item_id  =>  { data_type => 'integer', is_nullable => 0 },
  body => { data_type => 'text', default_value => undef, is_nullable => 1 },
  nick => { data_type => 'varchar', default_value => undef, is_nullable => 1 },
  email => { data_type => 'varchar', default_value => undef, is_nullable => 1 },
  web_site => { data_type => 'varchar', default_value => undef, is_nullable => 1 },
  ip => { data_type => 'varchar', default_value => undef, is_nullable => 1 },
  t_created => { data_type => 'datetime', set_on_create => 1 },
  t_updated => { data_type => 'datetime', set_on_create => 1, set_on_update => 1 },
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to('item', 'DBSchema::Item', { id => 'item_id' });

1;

This needs to be linked to the Item table - the thing that the comments belong to. I wander how can I package this - so that this could be variable.


Next the FormHandler form:

package CommentForm;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Model::DBIC';
with 'HTML::FormHandler::Render::Simple';

has '+item_class' => ( default => 'Comment' );

has_field body => ( type => 'TextArea', cols => 30, rows => 6, required => 1 );
has_field email => ( type => 'Email', required => 1 );
has_field web_site => ( type => 'URI' );
has_field nick => ( required => 1 );
has_field ip => ( widget => 'no_render' );
has_field item_id => ( widget => 'no_render' );
has_field submit => ( widget => 'submit', value => 'Add Comment' );

And finally the controller method for building the comment form and saving the comments:

sub stash_comment_form {
    my( $self, $c, @pks ) = @_;
    my $params = $c->req->params;
    my $form = CommentForm->new(
         schema => $c->model( $self->model_name ),
    );
    if( $c->req->method eq 'POST' ){
        $params->{item_id} = $pks[0];
        $params->{ip} = $c->req->address;
        $form->params( $params );
        if( $form->process ){
            $c->res->redirect( $c->uri_for( $self->redir_after_comment, @pks ) );
        }
    }
    $c->stash( comment_form => $form );
}

This can be called in any action that displays the comment form like this:

$self->stash_comment_form( $c, $pk )

For now I leave out the templates for displaying the comments - but this is rather simple.


Cook zby! I've been looking for some code implementations using HTML::FormHandler

My tags:
 
Popular tags:
 
Powered by Catalyst