root/lang/perl/Config-Multi/trunk/lib/Config/Multi.pm @ 11791

Revision 11791, 6.3 kB (checked in by tomyhero, 5 years ago)

lang/perl/Config-Multi : bug fix. 順番依存のところ、ハッシュでループまわしてた。配列にかえた。

Line 
1package Config::Multi;
2
3use strict;
4use warnings;
5use DirHandle;
6use File::Spec;
7use FindBin;
8use Config::Any;
9use Carp;
10
11use base qw/Class::Accessor/;
12
13our $VERSION = '0.03';
14
15__PACKAGE__->mk_accessors(qw/app_name prefix dir files extension/);
16
17sub load {
18    my $self  = shift;
19    my @files = ();
20    $self->{extension} ||= 'yml';
21    croak('you must set dir')      unless $self->{dir};
22    croak('you must set app_name') unless $self->{app_name};
23
24    my $config = {};
25
26    my $app_files = $self->_find_files( $self->{app_name} );
27    my $app = Config::Any->load_files( { files => $app_files } );
28    for ( @{$app} ) {
29        my ( $filename, $data ) = %$_;
30        push @files, $filename;
31        $config = { %{$config}, %{$data} };
32    }
33
34    if ( $self->{prefix} ) {
35        my $prefix_files
36            = $self->_find_files( $self->{prefix} . '_' . $self->{app_name} );
37        my $prefix = Config::Any->load_files( { files => $prefix_files } );
38        for ( @{$prefix} ) {
39            my ( $filename, $data ) = %$_;
40            push @files, $filename;
41            $config = { %{$config}, %{$data} };
42        }
43    }
44
45    my $local_files = $self->_local_files;
46    my $local = Config::Any->load_files( { files => $local_files } );
47    my $local_config = {} ;
48    for ( @{$local} ) {
49        my ( $filename, $data ) = %$_;
50        push @files, $filename;
51        $local_config->{$filename} = $data;
52    }
53
54    for (@{$local_files} ) {
55        $config = { %{$config}, %{ $local_config->{$_} } };
56    }
57
58    $self->{files} = \@files;
59
60    return $config;
61}
62
63sub _local_files {
64    my $self        = shift;
65    my $env_app_key = 'CONFIG_MULTI_' . uc( $self->{app_name} );
66    my $env_prefix_key
67        = 'CONFIG_MULTI_'
68        . uc( $self->{prefix} ) . '_'
69        . uc( $self->{app_name} );
70    my @files     = ();
71    my $app_lcoal = $ENV{$env_app_key}
72        || File::Spec->catfile( $self->dir,
73        $self->{app_name} . '_local.' . $self->extension );
74    push @files, $app_lcoal if -e $app_lcoal;
75
76    if ( $self->{prefix} ) {
77        my $prefix_local = $ENV{$env_prefix_key} || File::Spec->catfile(
78            $self->dir,
79            $self->{prefix} . '_'
80                . $self->{app_name}
81                . '_local.'
82                . $self->extension
83        );
84        push @files, $prefix_local if -e $prefix_local;
85    }
86
87    return \@files;
88}
89
90sub _find_files {
91    my $self      = shift;
92    my $path      = $self->dir;
93    my $label     = shift;
94    my $extension = $self->extension;
95
96    my @files;
97    my $dh = DirHandle->new($path) or croak "Could not Open " . $path;
98
99    while ( my $file = $dh->read() ) {
100        next if $file =~ /local\.$extension$/;
101        if (   $file =~ /^$label\.yml$/
102            || $file =~ /^$label\_(\w+)\.$extension$/ )
103        {
104            push @files, File::Spec->catfile( $path, $file );
105        }
106    }
107
108    return \@files;
109}
110
1111;
112
113=head1 NAME
114
115Config::Multi - load multiple config files.
116
117=head1 SYNOPSIS
118
119 use Config::Multi;
120 use File::Spec;
121 use FindBin;
122 
123 my $dir = File::Spec->catfile( $FindBin::Bin , 'conf' );
124
125 # prefix and extension is optional.
126 my $cm
127        = Config::Multi->new({
128            dir => $dir ,
129            app_name    => 'myapp' ,
130            prefix      => 'web' ,
131            extension   => 'yml'
132        });
133 my $config = $cm->load();
134 my $loaded_config_files = $cm->files;
135
136=head1 DESCRIPTION
137
138This module load multiple config files using L<Config::Any>. You can specify directory and put into your config files!
139
140I create this module because I want to load not only loading multiple config files but also switch config files depend on interface I am using. like,  I want to load web.yml only for web interface configuration and cli.yml for only for client interface configuration. let me explain step by step at EXAMPLE section.
141
142=head1 EXAMPLE
143
144=head2 your configuration files
145
146This is under your ~/myapp/conf/ and have yaml configuration in each files.  you can specify the directory using dir option.
147
148 .
149 |-- env-prefix.yml
150 |-- env.yml
151 |-- myapp.yml
152 |-- myapp_boin.yml
153 |-- myapp_local.yml
154 |-- myapp_oppai.yml
155 |-- never_load.yml
156 |-- web_myapp.yml
157 |-- web_myapp_cat.yml
158 |-- web_myapp_dog.yml
159 `-- web_myapp_local.yml
160
161=head2 switchable
162
163when you set app_name as 'myapp' and prefix as 'jobqueue' then below files are loaded
164
165 |-- myapp.yml
166 |-- myapp_boin.yml
167 |-- myapp_local.yml
168 |-- myapp_oppai.yml
169
170${app_name}.yml or ${app_name}_*.yml
171
172when you set app_name as 'myapp' and prefix as 'web' then below files are loaded
173
174 |-- myapp.yml
175 |-- myapp_boin.yml
176 |-- myapp_local.yml
177 |-- myapp_oppai.yml
178 |-- web_myapp.yml
179 |-- web_myapp_cat.yml
180 |-- web_myapp_dog.yml
181 `-- web_myapp_local.yml
182
183${prefix}_${myapp}.yml ${prefix}_${myapp}_*.yml
184
185YES! you can switch config files depend on what you set for app_name and prefix.
186
187=head2 overwrite rule.
188
189there is also overwriting rule. there are three steps for this.
190
191
192_local.yml file overwrite the other config setting
193
194 ${prefix}_${app_name}_local.yml
195 ${app_name}_local.yml
196
197${prefix}_ files overwrite ${app_name} config setting
198
199 ${app_name}.yml, ${app_name}_*.yml  (not include ${app_name}_local.yml)
200
201app config.
202
203 ${prefix}_${myapp}.yml ${prefix}_${myapp}_*.yml
204
205=head2 $ENV setting
206
207instead of ${prefix}_${app_name}_local.yml , you can specify the path with $ENV{CONFIG_MULTI_PREFIX_MYAPP}
208
209instead of ${app_name}_local.yml , you can specify the path with $ENV{CONFIG_MULTI_MYAPP}
210
211note. PREFIX = uc($prefix); MYAPP = uc($app_name)
212
213=head1 METHODS
214
215=head2 new
216 
217constructor SEE CONSTRUCTOR ARGUMENT section.
218
219=head2 load
220
221load config files and return config data.
222
223=head2 files
224
225get array references of loaded config files. You can use this method after call load() method.
226
227=head1 CONSTRUCTOR ARGUMENT
228
229=head2 app_name
230
231your application name. use [a-z]+ for format.
232
233=head2 prefix
234
235prefix name . use [a-z]+ for format. this is optional. if you did not set. only application config is loaded(include appname_local.yml if you have. )
236
237=head2 dir
238
239specify directory where your config files are located.
240
241=head2 extension
242
243you must specify extension for your config files. default is yml.
244
245=head1 SEE ALSO
246
247L<Config::Any>
248
249=head1 AUTHOR
250
251Tomohiro Teranishi <tomohiro.teranishi@gmail.com>
252
253=head1 COPYRIGHT
254
255This module is copyright 2008 Tomohiro Teranishi.
256
257=head1 LICENSE
258
259This library is free software; you can redistribute it and/or modify
260it under the same terms as Perl itself.
261
262=cut
263
Note: See TracBrowser for help on using the browser.