Forcing debug screen

adding ?dump_info=1 to the end of the URL will force your Catalyst app to die on that page and print the debug screen. This can be very handy when you're unsure as to why something you think ought to be present in your page isn't.


Nextalyzer

The nextalyzer script is useful for analyzing a set of Catalyst objects to determine what overrides what, which objects provide what functionality, etc.


Stash and TT templates

Anything that is in the stash is available to your TT templates. So, if you have a template that looks like this:

    <label>Manufacturer:           
        <select id="mfg"> 
            [% FOREACH mfg IN manufacturers %] 
            <option>[% mfg %]</option>                 
            [% END %] 
        </select> 
      </label> 

Then you might populate the stash as follows:

    $c->stash->{manufacturers} = [ 'First Mfg', 'Second Mfg', 'Third Mfg' ];

Note that we populate it with an arrayref, not a simple array.


FormValidator and CDBI's accessor_name

When using Catalyst::Plugin::FormValidator I discovered an error where one field wasn't updated. I used the scaffolding video as example and took the sub do_edit from the video:

sub do_edit : Local {
  my ( $self, $c, $id ) = @_;
  $c->form( optional => [ My::Table->columns ]);
  My::Table->retrieve($id)->update_from_form( $c->form );
  $c->forward('view');
}

BUT if you override the column names in your CDBI base class with the sub accessor_name you have to specify those instead of the real column names:

  $c->form( optional => [ 'columnname1', 'columnname2, 'columnname3' ]);

What is Protorype ?

Need info about how to use Prototype (and what the heck it even is)? Go over to the HTML::Prototype Manpage.


Inflating/Deflating Epoch from a database using DateTime::Format::Strptime

use DateTime::Format::Strptime;

my $formatter = DateTime::Format::Strptime->new(pattern=>'%Y-%m-%d %H:%M:%S');

__PACKAGE__->has_a(
    timestamp => 'DateTime',
    inflate => sub {
        DateTime->from_epoch(epoch=>shift,formatter=>$formatter);
    },
    deflate => 'epoch'
);

Inflating/Deflating PostgreSQL TIMESTAMP

Under Postgresql when using TIMESTAMP(0) WITH TIME ZONE I use the following.

Note That I currently use CDBI::Loader so I loop through my tables and look for any column that ends in "_time". "$self->loader" below returns the object returned by calling CDBI::Loader and @extra_classes is a list of classes that are not automatically loaded by CDBI::Loader (for example, Postgresql Views).

    use DateTime::Format::Pg;

    # Set default stringification format for display
    my $format = DateTime::Format::Strptime->new( pattern => '%a %b %d, %Y  %I:%M%P %Z');

    for my $class ( $self->loader->classes, @extra_classes ) {
        $class->has_a(
            $_    =>  'DateTime',
            inflate => sub { 
                my $dt = DateTime::Format::Pg->parse_datetime( shift );
                $dt->set_formatter( $format );

                return $dt
            },
            deflate => sub { DateTime::Format::Pg->format_datetime( shift ) },
        ) for grep { /_time$/ } $class->columns;
     }

Forcing a Trailing Slash

Most Web servers force a trailing slash on URIs which map to directories. For example, Apache issues a 301 redirect from http://www.example.com/about to http://www.example.com/about/ if about is a directory on the server.

In Catalyst, you can use Regex actions to simulate directories. For example:

sub show : Regex('people/([A-Za-z0-9]{8,9})/?$') {
    my ($self, $c) = @_;

    # ...
}

To get Catalyst to maintain the illusion that people contains a bunch of directories matching [A-Za-z0-9]{8,9}, add the following to your application:

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

    if ($c->req->action =~ /\/\?\$$/ and $c->req->path !~ /\/$/) {
        $c->res->redirect('/' . $c->req->path . '/', 301);
        return 0;
    }

    return 1;
}