make spelling tests pass
[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
491a1083 111concrete sub-roles.
c35b639e 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
491a1083 117Attributes specified directly as arguments to C<new_with_config> supersede those
fc44be6f 118in the configfile.
119
c35b639e 120L<MooseX::Getopt> knows about this abstract role, and will use it if available
491a1083 121to load attributes from the file specified by the command line flag C<--configfile>
c35b639e 122during its normal C<new_with_options>.
123
124=head1 Attributes
125
126=head2 configfile
127
491a1083 128This is a L<Path::Tiny> object which can be coerced from a regular path
2f049fc1 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
491a1083 155Explicit arguments will override anything set by the configfile.
c35b639e 156
157=head2 get_config_from_file
158
491a1083 159This class method is not implemented in this role, but it is required of all
160classes or roles that consume this role.
161Its two arguments are the class name and the configfile, and it is expected to return
fc44be6f 162a hashref of arguments to pass to C<new()> which are sourced from the configfile.
c35b639e 163
4d0a4f55 164=head1 COPYRIGHT
c35b639e 165
6210e5a5 166Copyright (c) - the MooseX::ConfigFromFile "AUTHOR" and "CONTRIBUTORS" as listed below.
c35b639e 167
168=head1 AUTHOR
169
170Brandon L. Black, E<lt>blblack@gmail.comE<gt>
171
4d0a4f55 172=head1 CONTRIBUTORS
173
174=over
175
a4f0ac9f 176=item Tomas Doran
4d0a4f55 177
178=item Karen Etheridge
179
180=item Chris Prather
181
182=item Zbigniew Lukasiak
183
184=back
185
c35b639e 186=head1 LICENSE
187
188This library is free software; you can redistribute it and/or modify
189it under the same terms as Perl itself.
190
191=cut