Docendo discimus


  • Calendar

    December 2021
    M T W T F S S
  • Archives

  • Recent Posts

  • Bling

Posts Tagged ‘introduction to catalyst’

Catalyst is easy – using the database

Posted by brunorc on September 19, 2009

There was not too much about doing the Catalyst things recently. I went into some musings about Perl: why it is cool, relevant and blah.

But recently I had a nice conversation with a friend, who works in the same company. He has a strong Java background, but frankly it didn’t turn him into a brainless, corporative ant. It’s quite interesting, but even now, when I work in the Perl-driven company, I find myself having conversations with Java people :-) And those conversations are mostly nice, so maybe that’s why I keep having them. Or maybe just those people are interesting and nice, regardless of their favourite programming language? Nevertheless, this guy also plays Magic – and he’s quite good at this. So there’s at least one thing that really unites us.

Anyway, I like his pragmatic point of view. And this conversation gave me the impulse to once again think about coolness and relevancy. A programming language is cool and relevant, if it helps you in writing programs, that solve your problems. If you can do it in a fast and consistent, elegant manner, then everything is OK. This compels me to cut my musings and go back to the real Perl.

First “useful” application shown here was a non-persistent life counter for a duel of Magic planeswalkers. If someone liked to make it more persistent, he would probably think about the database – you know, those huge things Oracle used to sell before people discovered that SQL must die, because Erlang is cooler. But for the Magic counter we don’t need Oracle, SQLite will be quite enough.

Now let’s go to the application directory – I assume you are able to type in your console:

sqlite3 magicount.db

and get output similar to this one:

SQLite version 3.4.0
Enter ".help" for instructions

which roughly translates to it works! If it doesn’t, go to the link above, download the SQLite for your operating system, install it and try again. If it works for you as well, it is the time to create the database and populate it:

sqlite> CREATE TABLE player ( id INTEGER PRIMARY KEY, name TEXT );
sqlite> INSERT INTO player (name) VALUES ('Bruno');
sqlite> INSERT INTO player (name) VALUES ('Betka');
sqlite> INSERT INTO player (name) VALUES ('Chris');
sqlite> INSERT INTO player (name) VALUES ('Giel');
sqlite> .quit

In SQLite, INTEGER PRIMARY KEY means that field will be autoincremented, so we don’t need to specify the value for id. After quitting we can check if there’s something inside:

sqlite3 magicount.db
SQLite version 3.4.0
Enter ".help" for instructions
sqlite> select * from player;

Who would expect, eh?

Now it is the time to create the new Model for the database. It is achieved by the following incantation:

script/ model MyModelName DBIC::Schema MySchemaClass create=static dbi:DB_type:how_to_get_the_DB

MyModelName looks rather obvious – it is the name of the model; it will be used later to access it, so it should be meaningful. MySchemaClass is – sure – the name of the class, representing the DB schema. The create option can have two values: static and dynamic, but since nowadays you can recreate your DB-based classes without losing the code written by yourself, static is the best choice. The last argument is the DSN, used by underlying DBI module – it should include the type of the database (so DBI can use the appropriate driver) and the way to access it (if you want some more elaborated description, check the documentation of the DBIC::Schema helper). So, in the end, everything should look like this:

script/ model MCDB DBIC::Schema MagiCount::Schema create=static dbi:SQLite:magicount.db

MCDB stands for MagiCount DataBase – not very fancy, but quite short. We use the SQLite driver and give the name of the file, where the database is stored. If everything is OK and you have installed all necessary modules (you can check the list here – usually they will be installed with the most important one, Catalyst::Model::DBIC::Schema, but this list may be handy in case of obstacles), you should get the similar output:

exists "/Users/bruno/devel/MagiCount/script/../lib/MagiCount/Model"
exists "/Users/bruno/devel/MagiCount/script/../t"
Dumping manual schema for MagiCount::Schema to directory /Users/bruno/devel/MagiCount/script/../lib ...
Schema dump completed.
created "/Users/bruno/devel/MagiCount/script/../lib/MagiCount/Model/"
created "/Users/bruno/devel/MagiCount/script/../t/model_MCDB.t"

Go take a look at the created files – probably the most interesting one will be lib/MagiCount/Schema/Result/

package MagiCount::Schema::Result::Player;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("InflateColumn::DateTime", "Core");
    data_type => "INTEGER",
    default_value => undef,
    is_nullable => 1,
    size => undef,
    data_type => "TEXT",
    default_value => undef,
    is_nullable => 1,
    size => undef,

# Created by DBIx::Class::Schema::Loader v0.04006 @ 2009-09-19 15:06:06

# You can replace this text with custom content, and it will be preserved on regeneration

As you can see, it is the Perl representation of the SQL code. Thanks to this Perl is aware of the structure of tables and all fields included. Also, the library that powers this stuff – DBIx::Class – is not only able to create such files from the existing database; you can use it the other way round, shaping your database with the Perl code, as DBIx::Class will create the structure of tables described in modules (check the documentation for DBIC). Also, you can freely add your code below the MD5 sum line and it will be maintained.

This all looks cool, but there’s a lot of stuff behind and around it, so now I will only show how to use it on a very simple example. Instead of writing the names of players in the form, we’re going to use the HTML select elements. In the create.tt2 file we can change:

      <label for="player1">Name of the first player</label>
      <input type="text" name="player1" size="12" /><br />


      <label for="player1">Name of the first player</label>
      <select name="player1">
        [% FOREACH player IN c.model('MCDB::Player').all %]
        <option value="[% %]">[% %]</option>
        [% END %]
      </select><br />

doing the same for the second player. And if we want to have players ordered alphabetically:

        [% FOREACH player IN c.model('MCDB::Player').all.sort('name') %]
        <option value="[% %]">[% %]</option>
        [% END %]

Of course we’re accessing Model from the View and doubling the amount of database calls. But at least our players are persistent! In the next episode: updating the contents of the table.

Posted in Catalyst for intimidated | Tagged: , , , , , , | Leave a Comment »

Catalyst is easy – feedback

Posted by brunorc on September 6, 2009

I’ve got some feedback from the user, asking about the installation of Catalyst on Windows. Peter asks:

I installed Catalyst in Windows in the way you said, but once it finished, I cant find the Catalyst folder. Where is it? How can I start with an easy Hello Work in using Catalyst?

Let me answer in two steps. First, Catalyst doesn’t have one, proper directory (or folder) – it gets installed on your system mostly as a bunch Perl modules, accompanied with some scripts (catalyst.bat on Windows, on Unix-likes). From this moment on, you can use this script to create any number of separate, independent Catalyst applications. You can even organize them, according to your needs or preferences – I would do it in the command window:

mkdir C:\Catalyst
cd C:\Catalyst
mkdir devel production
cd devel
catalyst.bat FaceSpace

Now you have your new Catalyst application residing under C:\Catalyst\devel\FaceSpace. After some time spent on working with it, you want to put it live. Then you can just copy the FaceSpace directory to the C:\Catalyst\production and it will continue to work. Now you have two copies of the app, and you can compare the “devel” version with the “production” one, but that will require some tweaking, as probably both servers will try to start on port 3000; the easiest solution for me would be to start the “production” version on port 3001 (you won’t need to restart it, as it is your point of reference):

cd C:\Catalyst\production\FaceSpace
perl script\ --port 3001

Catalyst - pure and simple

Catalyst - pure and simple

Of course after fixing some bug, it’s generally a good idea to copy the development version to C:\Catalyst\production again, and then restart the server (and update the real “production” version). You can also use some Version Control System for those tasks – I would encourage you to use git, as it is modern, cool, and well documented – but two directories are fine. If you find yourself juggling with many directories and their timestamped *.zip copies, then you definitely need VCS.

Making the long answer short: there is no special Catalyst folder, but any folder you create using the catalyst.bat script is an individual self-containing Catalyst folder.

And the second part – I’ve already written the helloworldish post, so please try it and if there’s something missing, I’d be glad to know how it can be improved.

Posted in Catalyst for intimidated | Tagged: , , , , , | 1 Comment »

Catalyst is easy – something useful

Posted by brunorc on July 30, 2009

Recently I haven’t had much time for writing, because I found a new toy. Somewhat demanding and time consuming toy. But even this toy couldn’t have completely attract all my attention, so some small part of it was still left in the dark corner of my consciousness labelled “Perl”. Soon I discovered that using Perl – and, of course, Catalyst – I can have even more fun playing with my new toy.

Now a short digression: the toy itself is not very new, only I was successfully introduced to it lately. It is the collectible card game, Magic: The Gathering. You may like it, you may hate it, or you may just have no clue about it – it doesn’t matter, as I still want to keep the profile of this blog: Perl, Catalyst, Moose and crap. Well, you can count Magic into the “crap” part if it makes you feel better.

Making long thing short, all I need is a small application, that would serve as a “life counter”. The game is based on the idea of the duel of two wizards. One must die, and that happens when his life counter reaches 0. When the game starts, both counters have the value of 20. As far as I know there is no upper limitation, so in the course of the game wizards can gain even more life. Now you may see why the game is so popular amongst programmers: they are often accused of having no life, and here they start with 20 and can gain even more!

Although there is the possibility of doing Magic in the multiplayer mode, we’re going to start with simple duel of two wizards. Let’s summarize the requirements:

  • two players – we will probably like to know her names
  • every player has a counter, that starts with 20 (with no upper limit); the game ends when one counter reaches 0
  • during the game we want to change the state of both counters, regardless of player’s turn; that’s because there’s a lot of possibilities in Magic, for instance a player can be dealt the damage caused by his own spell that has been redirected

I’m going to keep things simple, so there is no state, no authorization, nothing fancy. Everything will be put in the Root controller and there will be one model to keep the state of the game. I start with creating the application: MagiCount

Notice the advise, added recently:

Change to application directory and Run "perl Makefile.PL" to make sure your install is complete

It is probably a good idea to do this. Now I’m going to create my favourite View, and then the brand new Model:

script/ view TTS TTSite
# output skipped
script/ model Game

Now I’m ready to create the code for the Controller:

sub index :Path :Args(0) {
    my ( $self, $c ) = @_;
    $c->detach( $c->model('Game')->game ? 'play' : 'create' );

I want my actions to be controlled solely by the state of the game. So if the game is defined, I will be able to play – otherwise there’s a need to create one.

sub create :Private {
    my ( $self, $c ) = @_;

    my $p1 = $c->req->params->{player1};
    my $p2 = $c->req->params->{player2};
    my $ct = $c->req->params->{counter};

    if ( $p1 and $p2 ) {
        if ( $p1 eq $p2 ) {
            $c->stash->{errmsg} .= 'Names should be different';
        else {
                [ $p1, $p2 ],
                $ct ? [ $ct, $ct ] : undef


    $c->stash->{template} = 'create.tt2';

In lines 4-6 I’m going to catch the params if they are sent from the form. Then I check them against the obvious condition – players names should be different, otherwise they would start to quarrel about the score. If anything is OK, I intialize the game with the optional parameter – initial value of the counter. It is doubled and passed as an array reference. In that case I’m ready to play, so I use the detach method to exit this action and go directly to the action named play.

Apart from detach there’s also forward, which returns after the action the flow was forwarded to is completed.

Anyway, if the request doesn’t contain any parameters, I’m going to show the template with appropriate form.

sub play :Private {
    my ( $self, $c ) = @_;

    if ( $c->req->params->{close} ) {

    my $c1 = $c->req->params->{counter1};
    my $c2 = $c->req->params->{counter2};

    $c->stash->{game} = $c->model('Game')->game;

    if ( $c1 or $c2 ) {
        $c->stash->{game}->update( [ $c1, $c2 ] );

    $c->stash->{template} = 'play.tt2';

Now I start from the end: I close the game if requested, and then immediately go to create a new one. But if that’s not the case, I’m going to fetch the parameters from request, get the game object, and then update its state. Now the game is ready to be shown, so the only missing thing is the template.

sub default :Path {
    my ( $self, $c ) = @_;
    $c->response->body( 'Page not found' );

That is the standard default action. Nothing fancy.

Now to the Model. I decided to build a simple, singleton class. It will have one arrayref for the names, and then arrayref of arrayrefs for the state of the counters. Maybe it is a little bit convoluted, but will be easier to use in the View later.

my $game;

sub init {
    my ( $class, $names, $counters ) = @_;
    $game = {
        finished => 0,
        players  => $names,
        counters => [ $counters || [ 20, 20 ] ],

    return bless $game, ( ref $class );

First I create my singleton, which becomes a hash reference in line 6, and then – in line 12 – is blessed into the full-fledged class. I pass my names and counters as array references. This is the best way if I want to pass multiple arrays to a function; Perl 6 will have support for names, types and sizes of parameters, but in Perl 5 we have to use array references.

sub update {
    my ( $self, $updates ) = @_;

    push @{ $game->{counters} },
        [ map { $game->{counters}->[-1]->[$_] + $updates->[$_] } (0, 1) ];
    $game->{finished} = 1
        if grep { $_ <= 0 } @{ $game->{counters}->[-1] };

This method gets the array reference of modifiers and then applies them to the current state. I treat the $game->{counters} as an array, so I can push into this. Then I fetch the last item from this array (using the -1 index), and update its elements with respective values. Result of this operation is then pushed.

After this I check if both sorcerers are still alive. If one has deceased, I consider the game as finished. Again, I use the negative index to get the most up-to-date values.

sub close {
    undef $game;

sub game {
    return $game;

sub players {
    return $game->{players};

sub counters {
    return $game->{counters};

sub finished {
    return $game->{finished};

Closing the game means putting the singleton in the undefined state. The rest is just a bunch of accessors.

Now comes the View. No style, just pure HTML.

<h3>Create your game</h3>
<div style="color: red">[% errmsg %]</div>
<form action="" method="post">
      <label for="player1">Name of the first player</label>
       <input type="text" name="player1" size="12" /><br />
      <label for="player2">Name of the second player</label>
       <input type="text" name="player2" size="12" /><br />
       <label for="counter">Initial counter state</label>
       <input type="text" name="counter" size="2" /><br />
       <input type="submit" name="go" value="GO!" />

And the same for playing:

<form action="" method="post">
                <th><strong>[% game.players.0 %]</strong></th>
                <th><strong>[% game.players.1 %]</strong></th>
[% FOREACH state IN game.counters %]
                <td>[% state.0 %]</td><td>[% state.1 %]</td>
[% END %]
[% IF game.finished %]
                <td colspan="2">
                    <input type="submit" name="close" value="GAME OVER!" />
[% ELSE %]
                        <label for="counter1">Modify</label>
                        <input name="counter1" size="3" />
                        <label for="counter2">Modify</label>
                        <input name="counter2" size="3" />
                <td colspan="2">
                    <input type="submit" name="go" value="GO!" />
[% END %]

That’s all. Take out your decks!

Posted in Catalyst for intimidated | Tagged: , , , , | Leave a Comment »