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.sqlCREATE 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.tuse 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.pmsub 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.pmsub 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.pmsub 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)