Cold Hard Code

Better applications with MooseX::SimpleConfig.

First, a short preamble to the recipe I will present.  I had been trying hard to write up an entry here once every two weeks, focusing on substance.  I was falling behind on a draft entry so it was looking like 3 weeks was going to lapse before it was released.  It's a good article, though, on using Git and FastCGI for deployment management.  It was requiring some code-as-I-go, as it was largely a play thing and I'm not using it in production (which is something I typically refrain from writing about but in this case I was making an exception).  I was doing well, and tragedy hit and I lost my awesome nephew.  Since then, it's been very hard to engage myself in anything of importance, and I've really struggled.  Now, nearly 2 months after the terrible event I'm mentally recovering.  The outpour of support and encouragement has been amazing, and I'm truly grateful.  Now, on to business with a completely different recipe...

I posit the following statement which I hold true: Command-line applications are typically called with the same options specified.

With this in mind, it seems a gross oversight that the most commonly used command-line tools don't support configuration files to populate options and default state.  I would personally love to simply be able to do mysql --configfile work.yml.  Unfortunately, I am unable to.

Fortunately, Perl and Moose lovers can.  Allow me to introduce you to MooseX::SimpleConfig.  This fantastic role gives you the capability to bake in configuration into your application with very little fuss.  If you use MooseX::Getopt, most things are effectively free -- including the --configfile command line option to explicitly specify the configuration file.

Things, however, get better from there.  I found myself wanting to setup local overrides of configuration.  I desired something similar to the way that Catalyst merges in from myapp_local.yml, to myapp.yml (or .conf) and finally into the Perl packages for defaults.  What I ended up with is a way to just traverse a list of paths, and load the first one found.

It's a dead simple recipe:

with 'MooseX::SimpleConfig';
with 'MooseX::Getopt';

has +configfile => (
    default => ( grep { defined $_ and -f $_ } @list_of_places_to_look )[0] || ""
);

Now, you just need to setup your @list_of_places_to_look array, and you're set.  The first one found wins, and that's the config file.

To take it a step forward, on an application that has different projects or some othe binding feature, you could shorthand this using environment variables to bootstrap the project for smaller and more meaningful command lines:


# Populate like this:
my @list_of_places_to_look = (
   File::Spec->catdir($ENV{PROJECT}, 'etc'),
   File::Spec->catdir($ENV{HOME}, 'etc')
);
# And then:
$ PROJECT=foo myscript.pl
# Profit!
Now, if all you are doing is using your environment variable to set configuration paths, I'd say you are going down a wrong path.  However, using the project dir in a more substantial way (such as a Cwd call and using that project path as a place to store sockets or PID files) then I think it's a safe usage.

You'll see more of this when I finally do finish up the FastCGI and Git recipe, so stay tuned.
jshirley

Written by Jay Shirley

Jay Shirley combines technical fundamentals with modern, practical savvy. An open source veteran with plenty of notches in his personal and professional belt, the combination of his work and his field vision (soccer metaphor!) has few rivals.

Comments