[Catalyst] best practice: where to put constants

Bill Moseley moseley at hank.org
Thu Jun 4 19:14:42 GMT 2009


On Thu, Jun 04, 2009 at 10:23:11AM -0700, Jarom Smith wrote:
>
> You lost me.  I could probably figure out what you are saying, but would  
> you be willing to send some sample code illustrating what you're talking  
> about?  That would be very helpful to me, and possibly others.  Thanks!

Jarom,

To add one more to the mix, I put all configuration data into the
Catalyst config file, but constants that might be used outside of
Catalyst are in a Const.pm file that can be loaded by model classes.

The vast majority of settings are in my Catalyst config, and I end up
with very few in the Const.pm file.  Mostly things like database
constants are in Const.pm.  (Plus, I have utilities to make the
Catalyst config available to non-Catalyst scripts, like cron jobs).


In any module that needs a constant it's then:

    package MyApp::Model::Foo;

    # Import "ACTIVE PENDING DISABLED"
    use MyApp::Const ':user_status';

    ...

    if ( $user->status == PENDING ) {
        ...
    }

You could probably alter code below so that the constants have a
prefix of "USER_STATUS_" to give the feeling of name spaces.

The problem with this approach is that these constants are
subroutines.  See "perldoc Readonly" for discussion about this.


Here's an abbreviated example.  You can do the same thing just using
Exporter but this gave me a bit more flexibility on building my
constants.



package MyApp::Const;
use strict;
use warnings;
use Carp;

my %constants_map = (

    account_type => {
        SUBSCRIPTION => 1,
        PREPAID      => 2,
        GROUP        => 3,
    },

    user_status => {
        ACTIVE  => 1,
        PENDING => 2,
        DISABLED => 3,
    },
);

my %by_name;

# Create a flat list of constants and look for duplicates

for my $group_name ( keys %constants_map ) {
    for my $const ( keys %{ $constants_map{$group_name} } ) {
        die "Constant $const name already used" if exists $by_name{$const};
        $by_name{$const} = $constants_map{$group_name}{$const};
    }
}


# Export constants to caller name space

sub import {
    my ( $self, @export ) = @_;

    my $caller_pkg = caller || die 'no caller';

    no strict 'refs';    ## no critic

    for my $name ( @export ) {
        if ( $name =~ s/^:// ) {
            my $group = $constants_map{$name} || carp "Constant group ':$name' not found";
            for my $const ( keys %{$group} ) {
                my $sub_name = $caller_pkg . '::' . $const;
                *{$sub_name} = sub() { $group->{$const} };
            }
        }

        else {
            croak "Constant '$name' not found" unless exists $by_name{$name};
            my $sub_name = $caller_pkg . '::' . $name;
            *{$sub_name} = sub() { $by_name{$name} };
        }
    }

    return;

}


1;

-- 
Bill Moseley.
moseley at hank.org
Sent from my iMutt



More information about the Catalyst mailing list