I'm writing a perl application which uses Rose::DB for persistence abstraction, but I'm running into an issue with initializing my Rose::DB subclass with values from a configuration file.
The documentation always presents hardcoded examples, like:
# Register your lone data source using the default type and domain
__PACKAGE__->register_db(
driver => 'pg',
database => 'my_db',
host => 'localhost',
username => 'joeuser',
password => 'mysecret',
);
However, for maintainability's sake, I'd like to fill in these values from a separate config file at runtime.
The config file (Config::General format) section being used:
<database>
active_domain development
<db_domain development>
db_driver mysql
db_name stats_dev
db_host localhost
db_user stats_dev
db_password stats_dev
</db_domain>
<db_domain production>
db_driver mysql
db_name stats_prd
db_host localhost
db_user stats_prd
db_password stats_prd
</db_domain>
</database>
My Rose::DB subclass, with initializer method:
package Utils::DBUtils;
use strict;
use base qw(Rose::DB);
__PACKAGE__->use_private_registry;
sub registerAllDBs {
my ($self,$config_obj) = @_;
my $db_config = $config_obj->getDatabaseSection(); ## subconfig starts here
my $def_domain = $db_config->{"active_domain"};
__PACKAGE__->default_domain($def_domain);
__PACKAGE__->default_type('main');
my $db_domains = $db_config->{'db_domain'};
foreach my $domain (keys %$db_domains) {
my $domain_conf = $db_domains->{$domain};
__PACKAGE__->register_db(
domain => $domain,
type => __PACKAGE__->default_type(),
driver => $domain_conf->{'db_driver'},
database => $domain_conf->{'db_name'},
host => $domain_conf->{'db_host'},
username => $domain_conf->{'db_user'},
password => $domain_conf->{'db_password'}
);
}
}
1;
Then on my main script I call the method once to register all the data sources:
Utils::DBUtils->registerAllDBs($conf);
My persistent objects all inherit from the PersistentObject package, which initializes the DB object with:
sub init_db { Utils::DBUtils->new() }
However, this doesn't work as I expected. I get a compile-time error stating:
No database information found for domain 'default' and type 'default' and no driver type specified in call to Utils::DBUtils->new(...) at PersistentObject.pm line 9
The problem, it seems, is that Rose::DB expects to have the full configuration data at compile time, which would be not possible to provide since it comes from the config file.
Am I missing something here? Isn't it possible to dynamically initialize a Rose::DB object?
I have managed to get it to work, it seems that the Rose::DB subclass needs at least one register_db statement at compile time.
The (ugly) solution was to add
__PACKAGE__->register_db(
driver => 'mysql',
database => 'fake',
host => 'localhost',
username => 'fake',
password => 'fake'
);
to the package definition.