Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Abstracting Class::DBI Database Connection Data

by gryphon (Abbot)
on Jun 08, 2004 at 20:37 UTC ( #362539=perlquestion: print w/ replies, xml ) Need Help??
gryphon has asked for the wisdom of the Perl Monks concerning the following question:

Greetings fellow monks,

I'm playing around with Class::DBI again, and I'd really like to pass dynamic DSNs and other database connection information to my parent class from the calling script or application module. I've been using Config::IniFiles for a while now, and I really like it and would like to continue to use it. I've been toying with a few ideas on how to combine my various wants, and here's what I've come up with.

#!/usr/bin/perl use strict; use warnings; use Config::IniFiles; my $cfg; BEGIN { $cfg = new Config::IniFiles( -file => 'settings.ini' ); $ENV{_MyCDBI} = join("\t", $cfg->val('Database', 'dsn'), $cfg->val('Database', 'Username'), $cfg->val('Database', 'Password') ); } use MyCDBI;

I'm using use here just because it's habit and because it runs parallel to using other CPAN stuff and my own application modules. However, I could just as easily require instead of use to simplify things.

my $cfg = new Config::IniFiles( -file => 'settings.ini' ); $ENV{_MyCDBI} = join("\t", $cfg->val('Database', 'dsn'), $cfg->val('Database', 'Username'), $cfg->val('Database', 'Password') ); require MyCDBI;

Either way, I just split the various bits inside my Class::DBI parent.

package MyCDBI; use base 'Class::DBI::mysql'; __PACKAGE__->connection(split("\t", $ENV{_MyCDBI}));

Now, this works just fine, and I'm more or less happy with it for my purposes, but it's far from optimum. First of all, I'm using poor-man's serialization of the bits for the database connection. A better solution would include the capability of sending stuff like {AutoCommit => 1} and whatever else. Plus, the code in the calling script is somewhat obnoxious. I'd love to use use if possible, but even without, it's three lines long. I know if merlyn saw this, he'd cringe and use a one-liner alternative.

So my question is thus: What are some better ways of doing this? (Better = less lines of code, more flexible data sent, more class encapsulation, more coffee, etc.) One thing I was thinking about was writing an abstraction class for my parent Class::DBI class. I've always hated having to refer to the subclass names multiple times.

my $obj = MyCDBI::SomeDBObj->retrieve(1); # versus my $cls = new MyCDBI; my $obj = $cls->SomeDBObj->retrieve(1);

But I can't really say exactly why I don't like this.

I've been reading about Class::DBI::Factory, but I have to admit that much of it goes way over my head. Should I just grin and deal with the learning curve? Or is there a simpler way?

gryphon
code('Perl') || die;

Comment on Abstracting Class::DBI Database Connection Data
Select or Download Code
Re: Abstracting Class::DBI Database Connection Data
by hardburn (Abbot) on Jun 08, 2004 at 20:40 UTC

    Read the section of the Class::DBI doc titled "Dynamic Database Connections / db_Main".

    ----
    send money to your kernel via the boot loader.. This and more wisdom available from Markov Hardburn.

      Greetings hardburn,

      I have. Many times. But apparently I'm not smart enough to figure it out. This works:

      package MyCDBI; use base 'Class::DBI::mysql'; __PACKAGE__->connection('dbi:mysql:mydb', 'me', 'mypwd');

      But this doesn't:

      package MyCDBI; use base 'Class::DBI::mysql'; sub db_Main { use DBI; return DBI->connect('dbi:mysql:mydb', 'me', 'mypwd') or die DBI->errstr; }

      I get the nice error message: Can't locate object "fetch_hash" via package "DBI::st" at Class/DBI/mysql.pm line 65. The calling script only uses MyCDBI and prints a hello world, so there's nothing from that that's causing this. Any suggestions?

      gryphon
      code('Perl') || die;

        Doesn't db_Main have to return an Ima::DBI compatible handle now, rather then just a plain DBI handle?

        It says so, rather obliquely:

        The preferred method for doing this is to supply your own db_Main() method rather than calling connection(). This method should return a valid database handle, and should ensure it sets the standard attributes described above, preferably by combining $class->_default_attributes() with your own.

        I think the part about a valid database handle is where they mean one derived from Ima::DBI.

        Update:

        If you scan up right above the Dynamic Database Connections / db_Main heading, it says:

        We use the inherited RootClass of DBIx::ContextualFetch from Ima::DBI, and you should be very careful not to change this unless you know what you're doing!

        Maybe someone with a little more knowledge on this than I can provide a working example?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://362539]
Approved by tomhukins
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (10)
As of 2015-07-06 12:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (74 votes), past polls