Catalyst comes with a script for building the standard modules and directory structures. This is an excellent way to get started
bash $ catalyst.pl Sample::App created "Sample-App" created "Sample-App/script" created "Sample-App/lib" created "Sample-App/root" created "Sample-App/root/static" created "Sample-App/root/static/images" created "Sample-App/t" created "Sample-App/lib/Sample/App" .....
Create database. In this example we use PostgreSQL, but other databases are similar.
sql/schema-100.sql
CREATE SEQUENCE person_seq;
CREATE TABLE person (
person_id INT NOT NULL DEFAULT nextval('person_seq'),
firstname TEXT NOT NULL,
lastname TEXT NOT NULL,
nickname TEXT NOT NULL
);
ALTER TABLE person ADD
CONSTRAINT person_pk
PRIMARY KEY (person_id);
10 lines
package Sample::DB; use base qw/DBIx::Class::Schema/; __PACKAGE__->load_classes(qw/ Person /); 1;4 lines (14 total) lib/Sample/DB/Person.pm
package Sample::DB::Person;
use base 'DBIx::Class';
__PACKAGE__->load_components(qw/ PK::Auto::Pg Core /);
__PACKAGE__->table('person');
__PACKAGE__->add_columns(qw/ person_id firstname lastname nickname /);
__PACKAGE__->set_primary_key('person_id');
1;
7 lines (21 total)
Oops we forgot to create the test!
t/05dbic.t
use strict;
use warnings;
use Test::More tests => 2;
use lib 'lib';
BEGIN {
use_ok 'Sample::DB';
use_ok 'Sample::DB::Person';
};
Catalyst provides some tools for creating new Controllers, Models and Views.
This little script creates a new controller module and corresponding test.
bash $ script/sample_app_create.pl controller Person exists "lib/Sample/App/Controller" exists "t" created "lib/Sample/App/Controller/Person.pm" created "t/controller_Person.t"
The new controller class does not contain any methods yet.
lib/Sample/App/Controller/Person.pmpackage Sample::App::Controller::Person; use strict; use warnings; use base 'Catalyst::Controller'; 1;4 lines (25 total)
For a change we use the Petal template system. This borrows a Zope style XHTML syntax. You can use Mason, Template Toolkit or even Seamstress
bash $ script/sample_app_create.pl view Petal Petal exists "lib/Sample/App/View" exists "t" created "lib/Sample/App/View/Petal.pm created "t/view_Petal.t"
Again the new view class is very small!
lib/Sample/App/View/Petal.pmpackage Sample::App::View::Petal; use strict; use base 'Catalyst::View::Petal'; 1;4 lines (29 total)
We create our first action in the Person controller to use the Petal template system.
lib/Sample/App/Controller/Person.pm
sub end : Private {
my ($self, $c) = @_;
if ($c->stash->{template}) {
$c->forward('Sample::App::View::Petal');
}
else {
$c->res->redirect( '/person/list' );
}
}
9 lines (38 total)
List all the objects in the database
lib/Sample/App/Controller/Person.pm
sub list : Local {
my ($self, $c) = @_;
my $people = [$c->model('Schema::Person')
->search()
->all];
$c->stash->{people} = $people || [];
$c->stash->{add_link} = "location='/person/add';";
$_->{edit_link} = "location='/person/edit?id=".$_->person_id."';" for @$people;
$c->stash->{template} = 'person/list.html';
}
10 lines (48 total)
We do this in two steps, first displaying the edit form, and then updating the database
lib/Sample/App/Controller/Person.pm
sub edit : Local {
my ($self, $c) = @_;
my $person_id = $c->req->param('id');
my $person = $c->model('Schema::Person')
->find({ person_id => $person_id });
$c->stash->{person} = $person || {};
$c->stash->{template} = 'person/edit.html';
}
sub do_edit : Local {
my ($self, $c) = @_;
my $data = $c->req->params();
my $person = $c->model('Schema::Person')
->find({ person_id => $data->{person_id} });
$c->model('Schema')->schema->txn_do(sub {
$person->update($data);
}, $data);
}
18 lines (66 total)