http://qs321.pair.com?node_id=670464


in reply to Single file oriented for different usage

I have a way of doing it which I have found useful. Unfortunatly I cant take the credit for creating it.

This is the minimal form of it

package Foo::Config; use ... BEGIN { use Exporter; @EXPORT = qw/ &config /; # the following is the config data %config = ( dev => { A => {foo => 'dev_a'}, B => {this_is_not_foo => 'not_dev_b'}, _default => { foo => 'default_foo', database_env => 'dev_db', }, }, prod => { A => {foo => 'prod_a'}, B => {this_is_not_prod_foo => 'prod_b'}, _default => { foo => 'default_prod_foo', database_env => 'prod_db', }, }, _default => { A => { default_across_all_a_environments => 'def', }, _default => { the_same_everywhere => 1 }, }, # other stuff you want to run in the BEGIN block, i.e. set up the defa +ult environment. One thing i do is get a $environment variable based + on the hostname. } #END BEGIN sub config($) { my $field = shift; if (exists $config{$environment}->{$sub_environment}{$field} ) { return $config{$environment}->{$sub_environment}{$field}; }; if (exists $config{'_default'}->{$sub_environment}{$field} ) { return $config{'_default'}->{$sub_environment}{$field}; }; if (exists $config{$environment}->{'_default'}{$field} ) { return $config{$environment}->{'_default'}{$field}; }; if (exists $config{'_default'}->{'_default'}{$field} ) { return $config{'_default'}->{'_default'}{$field}; }; return undef; }
Then in my code i do the following:
use Foo::Config; my $config_var = config('foo');
The way it works is as follows. The %config defines all the configuration across all environment. In the case where we use it we have a production and development box, as well as a sub environment based on different countries (here A B and C). When a configuration variable is needed the config method is called. This then walks through the %config to pull out the correct variable.

There are several layers to it. From the most specific to the more general case:

  • $environment->$sub_env - This is details specific to that environment. I.e. the database schema may be specific to dev and production, as well as the sub-environment.
  • $environment->_default - this is for all elements within an environment which may be the same across an environment. For example development and production databases may be on different machines, but the same machine serves all sub-environments.
  • _default->$sub_env - this is for all elements which are consistent across all environments, but may be different for each sub-environment, i.e. a reply-to address for the email may be different for each country.
  • _default->_default - this is for all elements which are consistent across all environment. i.e. the body of an email you want to send out.

    The nice thing about this is that the more specific case will overwrite the more general ones. So its easy to change specific cases, i.e. a sub environment's database is moved to a new machine, so you only need to add a new config variable for that.

    Actually, re-reading your original post this doesn't really help with that problem. But i thought i might still post it as a nice solution ive found to multiple configuration problems.

  • Replies are listed 'Best First'.
    Re^2: Single file oriented for different usage
    by ack (Deacon) on Feb 28, 2008 at 15:52 UTC

      Hmmm. Most interesting. I just posted a reply to one of the other responses regarding a current issue that I, too, have regarding flexibility in processing Config files. This is actually a little closer to my specific problem and looks promising. Thanks for the code snippet. It'll give some good things to mull over.

      ack Albuquerque, NM