X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMooseX%2FConfigFromFile.pm;h=59d3e3ebd50b8235a950d587f165f0ee7e15ef28;hb=23fca8d5bbae73c0b80881f86126a86818035d6d;hp=29e82c920bebc18ceb8e69dc54a523b770a3ae86;hpb=7760bb42bcac9434f02e3e2d60a564ea777b31a1;p=gitmo%2FMooseX-ConfigFromFile.git diff --git a/lib/MooseX/ConfigFromFile.pm b/lib/MooseX/ConfigFromFile.pm index 29e82c9..59d3e3e 100644 --- a/lib/MooseX/ConfigFromFile.pm +++ b/lib/MooseX/ConfigFromFile.pm @@ -1,19 +1,28 @@ package MooseX::ConfigFromFile; +# ABSTRACT: An abstract Moose role for setting attributes from a configfile use Moose::Role; -use MooseX::Types::Path::Class qw( File ); - -our $VERSION = '0.02'; - +use MooseX::Types::Path::Tiny 0.005 'Path'; +use MooseX::Types::Moose 'Undef'; +use Try::Tiny; use Carp qw(croak); +use namespace::autoclean; requires 'get_config_from_file'; has configfile => ( is => 'ro', - isa => File, + isa => Path|Undef, coerce => 1, predicate => 'has_configfile', + do { try { require MooseX::Getopt; (traits => ['Getopt']) } }, + lazy => 1, + # it sucks that we have to do this rather than using a builder, but some old code + # simply swaps in a new default sub into the attr definition + default => sub { + my $class = shift; + $class->_get_default_configfile if $class->can('_get_default_configfile'); + }, ); sub new_with_config { @@ -25,11 +34,26 @@ sub new_with_config { $configfile = $opts{configfile} } else { + # This would only succeed if the consumer had defined a new configfile + # sub to override the generated reader - as suggested in old + # documentation -- or if $class is an instance not a class name + $configfile = try { $class->configfile }; + + # this is gross, but since a lot of users have swapped in their own + # default subs, we have to keep calling it rather than calling a + # builder sub directly - and it might not even be a coderef either my $cfmeta = $class->meta->find_attribute_by_name('configfile'); - $configfile = $cfmeta->default if $cfmeta->has_default; + $configfile = $cfmeta->default if not defined $configfile and $cfmeta->has_default; + + if (ref $configfile eq 'CODE') { + $configfile = $configfile->($class); + } + + my $init_arg = $cfmeta->init_arg; + $opts{$init_arg} = $configfile if defined $configfile and defined $init_arg; } - if(defined $configfile) { + if (defined $configfile) { my $hash = $class->get_config_from_file($configfile); no warnings 'uninitialized'; @@ -48,10 +72,6 @@ __END__ =pod -=head1 NAME - -MooseX::ConfigFromFile - An abstract Moose role for setting attributes from a configfile - =head1 SYNOPSIS ######## @@ -60,9 +80,9 @@ MooseX::ConfigFromFile - An abstract Moose role for setting attributes from a co package MooseX::SomeSpecificConfigRole; use Moose::Role; - + with 'MooseX::ConfigFromFile'; - + use Some::ConfigFile::Loader (); sub get_config_from_file { @@ -82,7 +102,7 @@ MooseX::ConfigFromFile - An abstract Moose role for setting attributes from a co with 'MooseX::SomeSpecificConfigRole'; # optionally, default the configfile: - has +configfile ( default => '/tmp/foo.yaml' ); + sub _get_default_configfile { '/tmp/foo.yaml' } # ... insert your stuff here ... @@ -94,31 +114,37 @@ MooseX::ConfigFromFile - An abstract Moose role for setting attributes from a co =head1 DESCRIPTION -This is an abstract role which provides an alternate constructor for creating +This is an abstract role which provides an alternate constructor for creating objects using parameters passed in from a configuration file. The actual implementation of reading the configuration file is left to -concrete subroles. +concrete sub-roles. It declares an attribute C and a class method C, and requires that concrete roles derived from it implement the class method C. -Attributes specified directly as arguments to C supercede those +=for stopwords configfile + +Attributes specified directly as arguments to C supersede those in the configfile. L knows about this abstract role, and will use it if available -to load attributes from the file specified by the commandline flag C<--configfile> +to load attributes from the file specified by the command line flag C<--configfile> during its normal C. =head1 Attributes =head2 configfile -This is a L object which can be coerced from a regular pathname -string. This is the file your attributes are loaded from. You can add a default -configfile in the class using the role and it will be honored at the appropriate time: +This is a L object which can be coerced from a regular path +string or any object that supports stringification. +This is the file your attributes are loaded from. You can add a default +configfile in the consuming class and it will be honored at the appropriate +time; see below at L. - has +configfile ( default => '/etc/myapp.yaml' ); +If you have L installed, this attribute will also have the +C trait supplied, so you can also set the configfile from the +command line. =head1 Class Methods @@ -130,27 +156,19 @@ C. Example: my $foo = SomeClass->new_with_config(configfile => '/etc/foo.yaml'); -Explicit arguments will overide anything set by the configfile. +Explicit arguments will override anything set by the configfile. =head2 get_config_from_file -This class method is not implemented in this role, but it is required of all subroles. -Its two arguments are the classname and the configfile, and it is expected to return +This class method is not implemented in this role, but it is required of all +classes or roles that consume this role. +Its two arguments are the class name and the configfile, and it is expected to return a hashref of arguments to pass to C which are sourced from the configfile. -=head2 meta - -The Moose meta stuff, included here because otherwise pod tests fail sometimes - -=head1 BUGS - -=head1 AUTHOR - -Brandon L. Black, Eblblack@gmail.comE - -=head1 LICENSE +=head2 _get_default_configfile -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. +This class method is not implemented in this role, but can and should be defined +in a consuming class or role to return the default value of the configfile (if not +passed into the constructor explicitly). =cut