Thursday, April 24, 2008

Creating a controller in Catalyst

A new controller in Catalyst is registered by running script/APPNAME_create.pl CONTROLLER_NAME. This creates a module in the controller directory and a test in the test directory. These are apparently all that is needed for a controller to be created.

It's worth noting that /foo can activate either App::Controller::Foo::index() or App::Controller::Root::foo(). However, if both exist, App::Controller::Foo::index() takes precedence.

Monday, April 21, 2008

Module Monday: Quantum::Superpositions

A new weekly feature. I'm going to dig out some of the hidden gems of CPAN. One of the best places to look is Damian Conway's list of modules and this is one fun and interesting one.

Here's a selection of what Quantum::Superpositions can do:

$wanted = any("Mr","Ms").any(@names);
if ($name eq $wanted) { print "Reward!"; }

$okay = all(\&check1,\&check2);
die unless $okay->();

my $large =
all( BigNum->new($centillion),
BigNum->new($googol),
BigNum->new($SkewesNum)
);
@huge = grep {$_ > $large} @nums;

Sunday, April 20, 2008

Installing Rose::DB::Object

For the Backlog project, I was thinking this was going to be a good opportunity to also learn Rose::DB::Object, so I tried installing it via CPAN. Oops, it had some errors along the way. It turns out that SQL::ReservedWords has a dependency on Data::OptList which it doesn't declare. Installing Data::OptList solved that problem, but Rose::DB::Object is still failing its test suite:

t/db-object-manager..................7/3900 Can't locate object method "format_select_start_sql" via package "Rose::DB::__RoseDBPrivate__::Rose::DB::MySQL" at /Users/dhosek/.cpan/build/Rose-DB-Object-0.769-AXgKMz/blib/lib/Rose/DB/Object/QueryBuilder.pm line 725.
# Looks like you planned 3900 tests but only ran 827.
# Looks like your test died just after 827.
t/db-object-manager.................. Dubious, test returned 255 (wstat 65280, 0xff00)
Failed 3073/3900 subtests
(less 783 skipped subtests: 44 okay)

My insomnia feels resolved, so I'll come back to this after sleep.

Update (21 April): I managed to solve the problem: Doing an install of Rose::DB::MySQL then re-trying to install Rose::DB::Object managed to do the trick.

Friday, April 18, 2008

Learning Catalyst: The Backlog project. Day 1

The Plan

What I'm looking to build is a web application which is designed for maintaining a product backlog. I see the following as the key user stories:
  • As a programmer, I want the system to use the wiki as its primary display and authentication system (so, users will log into Backlog using their wiki credentials, and the backlog is visible from the wiki).
  • As a programmer, I want the system to import the existing backlog from the wiki.
  • As a User, I want to be able to submit stories to the product backlog.
  • As a product owner, I want to be able to prioritize and arrange the backlog.


Installing Catalyst

This went far more easily than I expected. A simple CPAN install brought it in with no problems. I guess I was just lucky on that front.

Building the core

Step one was to build the core of the application. I ran catalyst.pl from the command line and got the following:

~/dev/Backlog> catalyst.pl Backlog
To use the Catalyst development tools including catalyst.pl and the
generated script/myapp_create.pl you need Catalyst::Helper, which is
part of the Catalyst-Devel distribution. Please install this via a
vendor package or by running one of -

perl -MCPAN -e 'install Catalyst::Devel'
perl -MCPANPLUS -e 'install Catalyst::Devel'


Apparently the Catalyst package is divided into two parts, one just for running Catalyst, one for developing Catalyst applications. Fortunately this install was also uneventful.

Rerunning it, I got

~/dev/Backlog> catalyst.pl Backlog
created "Backlog"
created "Backlog/script"
created "Backlog/lib"
created "Backlog/root"
created "Backlog/root/static"
created "Backlog/root/static/images"
created "Backlog/t"
created "Backlog/lib/Backlog"
created "Backlog/lib/Backlog/Model"
created "Backlog/lib/Backlog/View"
created "Backlog/lib/Backlog/Controller"
created "Backlog/backlog.yml"
created "Backlog/lib/Backlog.pm"
created "Backlog/lib/Backlog/Controller/Root.pm"
created "Backlog/README"
created "Backlog/Changes"
created "Backlog/t/01app.t"
created "Backlog/t/02pod.t"
created "Backlog/t/03podcoverage.t"
created "Backlog/root/static/images/catalyst_logo.png"
created "Backlog/root/static/images/btn_120x50_built.png"
created "Backlog/root/static/images/btn_120x50_built_shadow.png"
created "Backlog/root/static/images/btn_120x50_powered.png"
created "Backlog/root/static/images/btn_120x50_powered_shadow.png"
created "Backlog/root/static/images/btn_88x31_built.png"
created "Backlog/root/static/images/btn_88x31_built_shadow.png"
created "Backlog/root/static/images/btn_88x31_powered.png"
created "Backlog/root/static/images/btn_88x31_powered_shadow.png"
created "Backlog/root/favicon.ico"
created "Backlog/Makefile.PL"
created "Backlog/script/backlog_cgi.pl"
created "Backlog/script/backlog_fastcgi.pl"
created "Backlog/script/backlog_server.pl"
created "Backlog/script/backlog_test.pl"
created "Backlog/script/backlog_create.pl"

running ./Backlog/script/backlog_server.pl started up the web server on port 3000 and I was able to verify that I had a working Catalyst application to begin playing with.

Thursday, April 17, 2008

The @INC array can be more dynamic than you think

We can put subroutine references, array references and objects into the @INC array. See perldoc -f require for the hairy details.

Tuesday, April 15, 2008

Test-first doesn't mean every test must be written before you start coding

It's worth noting that test-first doesn't mean that all the tests have to be written before any code is written. In fact, in some cases, it's actually impossible to write the test before the implementation is at least partly scoped out (e.g., when it's necessary to mock objects or modules external to what you're testing). A lot of test cases end up coming up during the development process. Just like elsewhere in agile development, the secret is in tight loops. Write the test as soon as possible, but no sooner than necessary.

Monday, April 7, 2008

Installing DBD::mysql on OS X Leopard 10.5.2

One of those minor nightmare installs. I need this though, so I've gotta work for a while.

Here is the problem that shows up:

~/.cpan/build/DBD-mysql-4.006-j5Hpiv> prove -v -l t/00base.t
t/00base......
1..5
ok 1
ok 2
ok 3
install_driver(mysql) failed: Can't locate loadable object for module DBD::mysql in @INC (@INC contains: /Users/dhosek/.cpan/build/DBD-mysql-4.006-j5Hpiv/lib /Users/dhosek/.cpan/build/DBD-mysql-4.006-j5Hpiv/lib /System/Library/Perl/5.8.8/darwin-thread-multi-2level /System/Library/Perl/5.8.8 /Library/Perl/5.8.8/darwin-thread-multi-2level /Library/Perl/5.8.8 /Library/Perl /Network/Library/Perl/5.8.8/darwin-thread-multi-2level /Network/Library/Perl/5.8.8 /Network/Library/Perl /System/Library/Perl/Extras/5.8.8/darwin-thread-multi-2level /System/Library/Perl/Extras/5.8.8 /Library/Perl/5.8.6 /Library/Perl/5.8.1 .) at (eval 3) line 3
Compilation failed in require at (eval 3) line 3.
Perhaps a module that DBD::mysql requires hasn't been fully installed
at t/00base.t line 38
Dubious, test returned 2 (wstat 512, 0x200)
Failed 2/5 subtests

Test Summary Report
-------------------
t/00base.t (Wstat: 512 Tests: 3 Failed: 0)
Non-zero exit status: 2
Parse errors: Bad plan. You planned 5 tests but ran 3.


First step, is that I'm finding that the blib/arch/auto/DBD/mysql/mysql.so file is not being created.

Actually, that's not the problem! Looking closer, I'm seeing that the .bs and .bundle files are apparently the ones that apply now. Interestingly using prove -b t/00base.t does in fact work. But make test has the same test fail...

Ignoring that issue, I move on to the next test:

prove -b t/10connect.t
t/10connect......dyld: lazy symbol binding failed: Symbol not found: _mysql_server_init
Referenced from: /Users/dhosek/.cpan/build/DBD-mysql-4.006-j5Hpiv/blib/arch/auto/DBD/mysql/mysql.bundle
Expected in: dynamic lookup

dyld: Symbol not found: _mysql_server_init
Referenced from: /Users/dhosek/.cpan/build/DBD-mysql-4.006-j5Hpiv/blib/arch/auto/DBD/mysql/mysql.bundle
Expected in: dynamic lookup

t/10connect...... Failed 2/2 subtests

Test Summary Report
-------------------
t/10connect.t (Wstat: 5 Tests: 0 Failed: 0)
Parse errors: Bad plan. You planned 2 tests but ran 0.
Files=1, Tests=0, 0 wallclock secs ( 0.01 usr 0.00 sys + 0.04 cusr 0.00 csys = 0.05 CPU)
Result: FAIL


Update: 11 April 2008 The problem has its roots in using the pre-compiled distribution of mysql from mysql.com rather than building from source. This resulted in getting incompatible libraries between what was compiled for DBD::mysql and what I had in the mysql directory. Building from source resolved the problem. Good instructions on doing the job are available at HiveLogic.