convert to dist.ini
[gitmo/MooseX-ConfigFromFile.git] / lib / MooseX / ConfigFromFile.pm
CommitLineData
c35b639e 1package MooseX::ConfigFromFile;
2
3use Moose::Role;
2f049fc1 4use MooseX::Types::Path::Tiny 'Path';
0e88ec88 5use Try::Tiny qw/ try /;
870afbfa 6use Carp qw(croak);
bc5ab785 7use namespace::autoclean;
8
c35b639e 9requires 'get_config_from_file';
10
11has configfile => (
12 is => 'ro',
2f049fc1 13 isa => Path,
c35b639e 14 coerce => 1,
15 predicate => 'has_configfile',
742b859c 16 do { try { require MooseX::Getopt; (traits => ['Getopt']) } },
c35b639e 17);
18
19sub new_with_config {
20 my ($class, %opts) = @_;
21
fc44be6f 22 my $configfile;
23
24 if(defined $opts{configfile}) {
25 $configfile = $opts{configfile}
26 }
27 else {
7acf2fe9 28 # This would only succeed if the consumer had defined a new configfile
29 # sub to override the generated reader
f1040206 30 $configfile = try { $class->configfile };
7acf2fe9 31
32 # this is gross, but since a lot of users have swapped in their own
33 # default subs, we have to keep calling it rather than calling a
34 # builder sub directly - and it might not even be a coderef either
35 my $cfmeta = $class->meta->find_attribute_by_name('configfile');
a665bd30 36 $configfile = $cfmeta->default if not defined $configfile and $cfmeta->has_default;
7acf2fe9 37
56e4351b 38 if (ref $configfile eq 'CODE') {
83f0ce54 39 $configfile = $configfile->($class);
56e4351b 40 }
fc44be6f 41 }
42
0e88ec88 43 if (defined $configfile) {
870afbfa 44 my $hash = $class->get_config_from_file($configfile);
45
46 no warnings 'uninitialized';
47 croak "get_config_from_file($configfile) did not return a hash (got $hash)"
48 unless ref $hash eq 'HASH';
49
50 %opts = (%$hash, %opts);
c35b639e 51 }
fc44be6f 52
c35b639e 53 $class->new(%opts);
54}
55
56no Moose::Role; 1;
57
58__END__
59
60=pod
61
62=head1 NAME
63
64MooseX::ConfigFromFile - An abstract Moose role for setting attributes from a configfile
65
66=head1 SYNOPSIS
67
68 ########
69 ## A real role based on this abstract role:
70 ########
71
72 package MooseX::SomeSpecificConfigRole;
73 use Moose::Role;
74
75 with 'MooseX::ConfigFromFile';
76
77 use Some::ConfigFile::Loader ();
78
79 sub get_config_from_file {
80 my ($class, $file) = @_;
81
82 my $options_hashref = Some::ConfigFile::Loader->load($file);
83
84 return $options_hashref;
85 }
86
87
88 ########
89 ## A class that uses it:
90 ########
91 package Foo;
92 use Moose;
93 with 'MooseX::SomeSpecificConfigRole';
94
fc44be6f 95 # optionally, default the configfile:
7acf2fe9 96 around configfile => sub { '/tmp/foo.yaml' };
fc44be6f 97
c35b639e 98 # ... insert your stuff here ...
99
100 ########
101 ## A script that uses the class with a configfile
102 ########
103
104 my $obj = Foo->new_with_config(configfile => '/etc/foo.yaml', other_opt => 'foo');
105
106=head1 DESCRIPTION
107
108This is an abstract role which provides an alternate constructor for creating
109objects using parameters passed in from a configuration file. The
110actual implementation of reading the configuration file is left to
111concrete subroles.
112
113It declares an attribute C<configfile> and a class method C<new_with_config>,
114and requires that concrete roles derived from it implement the class method
115C<get_config_from_file>.
116
fc44be6f 117Attributes specified directly as arguments to C<new_with_config> supercede those
118in the configfile.
119
c35b639e 120L<MooseX::Getopt> knows about this abstract role, and will use it if available
121to load attributes from the file specified by the commandline flag C<--configfile>
122during its normal C<new_with_options>.
123
124=head1 Attributes
125
126=head2 configfile
127
2f049fc1 128This is a L<Path::Tiny> object which can be coerced from a regular pathname
129string or any object that supports stringification.
130This is the file your attributes are loaded from. You can add a default
7acf2fe9 131configfile in the consuming class and it will be honored at the appropriate time
132(note that a simple sub declaration is not sufficient, as there is already a
133sub by that name being added by Moose as the attribute reader)
fc44be6f 134
7acf2fe9 135 around configfile => sub { '/etc/myapp.yaml' };
c35b639e 136
4d0a4f55 137Note that you can alternately just provide a C<configfile> method which returns
138the config file when called - this will be used in preference to the default of
139the attribute.
140
742b859c 141If you have L<MooseX::Getopt> installed, this attribute will also have the
142C<Getopt> trait supplied, so you can also set the configfile from the
143command line.
144
c35b639e 145=head1 Class Methods
146
147=head2 new_with_config
148
149This is an alternate constructor, which knows to look for the C<configfile> option
150in its arguments and use that to set attributes. It is much like L<MooseX::Getopts>'s
151C<new_with_options>. Example:
152
153 my $foo = SomeClass->new_with_config(configfile => '/etc/foo.yaml');
154
155Explicit arguments will overide anything set by the configfile.
156
157=head2 get_config_from_file
158
159This class method is not implemented in this role, but it is required of all subroles.
160Its two arguments are the classname and the configfile, and it is expected to return
fc44be6f 161a hashref of arguments to pass to C<new()> which are sourced from the configfile.
c35b639e 162
4d0a4f55 163=head1 COPYRIGHT
c35b639e 164
6210e5a5 165Copyright (c) - the MooseX::ConfigFromFile "AUTHOR" and "CONTRIBUTORS" as listed below.
c35b639e 166
167=head1 AUTHOR
168
169Brandon L. Black, E<lt>blblack@gmail.comE<gt>
170
4d0a4f55 171=head1 CONTRIBUTORS
172
173=over
174
a4f0ac9f 175=item Tomas Doran
4d0a4f55 176
177=item Karen Etheridge
178
179=item Chris Prather
180
181=item Zbigniew Lukasiak
182
183=back
184
c35b639e 185=head1 LICENSE
186
187This library is free software; you can redistribute it and/or modify
188it under the same terms as Perl itself.
189
190=cut