[Catalyst] example of sep db config args (was Re: Accessing DB from
external model)
Darren Duncan
darren at darrenduncan.net
Sat Nov 6 18:57:18 GMT 2010
P.S. While answering a question, this email could be adapted for a Catalyst
cookbook / etc entry if one wants to.
Octavian Rasnita wrote:
> I agree and yes, that sample code could give bad ideas.
> In my case I am the app designer, coder, maintainer, site admin, everything but the web designer and I've done it so for not specifying these settings in more places.
I have the same role in my situation, but I also designed the project so it is
easier for someone else to come along and maintain it.
> Is there another place where I could put these settings for a certain DBIC schema?
> For example, can I put them in the MyApp/Schema.pm, orsomewhere else? Can you give an example?
I can show you a simplified version of what I have done, but with any
identifying details changed to protect the innocent. My version uses straight
DBI+DBIx::Connector rather than DBIC but you should be able to adapt the design
to DBIC or any other database API; my version is also Pg-specific but only minor
tweaks would be needed to work with something else. Since this is from a
proprietary application rather than a CPAN module, I can get away with requiring
and exploiting the latest Perl version, 5.12.x, rather than giving those up to
support older Perls.
1. Here is the relevant portion of MyApp.conf, which uses Config::General as
per Catalyst's default these days.
<Model DB>
<args>
db_host localhost
db_port 5444
db_name myproj_v1_db
db_user myproj_v1_usr_myapp
db_pass myapppass
</args>
</Model>
2. Here is the slightly simplified version of MyApp/Model/DB.pm, which uses
Catalyst::Model::Adaptor, and in such a way to support different class and file
names (requires 0.09+):
use 5.012002;
use utf8;
use warnings FATAL => 'all';
use MyDBMSLib 0.001;
package MyApp::Model::DB 0.001;
use parent 'Catalyst::Model::Adaptor'; # requires >= 0.09
__PACKAGE__->config( class => 'MyDBMSLib' );
1;
3. Here is a complete/template content of MyDBMSLib.pm; the original had
multiple classes in it but I removed the other ones and simplified the main one;
the original file was named after a different package than what I kept:
use 5.012002;
use utf8;
use warnings FATAL => 'all';
use DBIx::Connector;
use DBI;
use DBD::Pg;
###########################################################################
###########################################################################
{ package MyDBMSLib 0.001; # class
use namespace::autoclean;
use Try::Tiny;
use Moose;
has 'db_host' => (is => 'ro', isa => 'Str', required => 1 );
has 'db_port' => (is => 'ro', isa => 'Int', required => 1 );
has 'db_name' => (is => 'ro', isa => 'Str', required => 1 );
has 'db_user' => (is => 'ro', isa => 'Str', required => 1 );
has 'db_pass' => (is => 'ro', isa => 'Str', required => 1 );
# This is the actual (as far as we're concerned) Pg database connection
# object; the connection is opened the first time the _dbc attr is read
# and it is closed when the _dbc attr is garbage collected.
has '_dbc' => (
is => 'ro',
isa => 'DBIx::Connector',
required => 1,
lazy => 1,
default => \&_lazy_default_for_dbc,
);
###########################################################################
sub _lazy_default_for_dbc {
my ($process) = @_;
my $dbc = try {
my $dsn = sprintf( q{dbi:Pg:dbname=%s;host=%s;port=%s},
$process->db_name(), $process->db_host(), $process->db_port() );
my $dbc = DBIx::Connector->new( $dsn,
$process->db_user(), $process->db_pass(),
{ 'RaiseError' => 1, 'AutoCommit' => 1 },
);
my $dbh = $dbc->dbh();
# SET UP ANY OTHER CLIENT SETTINGS HERE ON $dbh
return $dbc;
}
catch {
confess sprintf( q{Could not open connection to Pg server or db:
%s}, $_ );
};
return $dbc;
}
###########################################################################
# PUT OTHER USEFUL MyDBMSLib METHODS HERE
###########################################################################
__PACKAGE__->meta()->make_immutable();
} # class MyDBMSLib
###########################################################################
###########################################################################
1;
For your version, mainly just replace _dbc with an object of whatever initial
class you have with DBIC that takes the db connection config args.
Your analogy to _lazy_default_for_dbc is where you feed DBIC its actual config
args, where some can be defined in MyDBMSLib itself and others taken from the
config file.
-- Darren Duncan
More information about the Catalyst
mailing list