在我之前的问题Moose - Loading values from conf files...中,杰克·马尼非常友好地提供了一个如何使用穆斯这样做的例子。
为了使配置对象更加通用,我决定使用Config::Auto。
问题在于,我对于穆斯如何运作仍然非常环保。例如,杰克的例子是:
package My::Module;
use Moose;
has 'config'=>(isa=>'HashRef[Str]',is=>'rw',required=>1);
around BUILDARGS=>sub
{
my $orig=shift;
my $class=shift;
my $args=shift; #other arguments passed in (if any).
my %config_hash=();
open(my $read,"<","config_file") or confess $!;
while(<$read>)
{
chomp;
my @array=split /:/;
$config_hash{$array[0]}=$array[1];
}
close($read);
$args->{config}=\%config_hash;
return $class->$orig($args);
};
no Moose;
1;
我已将其修改为:
#!/usr/local/bin/perl
package DART::Setup;
use namespace::autoclean;
use Moose;
use Config::Auto;
our $VERSION = '0.0.1';
has 'EMPTY' => ( isa => 'Str', is => 'ro', default => q{} );
has 'PPLTESTEXECUTIONID' => ( isa => 'Int', is => 'ro', default => 0 );
has 'SARQTESTEXECUTIONID' => ( isa => 'Int', is => 'ro', default => 0 );
has 'ISPROXY' => ( isa => 'Int', is => 'ro', default => 0 );
has 'LOCALHOST' => ( isa => 'Str', is => 'ro', default => '127.0.0.1' );
has 'config'=>(isa=>'HashRef[Str]',is=>'rw',required=>1);
has 'SSO' => ( isa => 'Str', is => 'rw', default => q{} );
has 'cookieFile' => ( isa => 'Str', is => 'rw', default => q{} );
around BUILDARGS=>sub
{
my $orig=shift;
my $class=shift;
my $args=shift;
my $cfg = Config::Auto::parse($args);
my %config_hash = %{$cfg};
$args->{config}=\%config_hash;
return $class->$orig($args);
};
return 1;
但说实话,我不确定我在这里做什么。首先,我在创建新的Setup对象时需要提供多少个参数?我只是将它传递给配置文件的路径,例如:
my $newConfig = DART::Setup->new('/home/y/conf/MyApp/MyApp.cfg');
或者我是否需要为$ orig和$ class提供参数?
最后,我现在如何访问新加载的配置?我可以这样做:
my %configHash = %{$newConfig->config()};
foreach my $key (keys %configHash) {
print "the key is, $key, and the value is: $configHash{$key}\n";
}
我是否正确理解了这一点?
答案 0 :(得分:1)
好的,在BUILDARGS
内,你想读入配置文件并将键值对传递给config
属性。这是一个修改版本,其中包含配置文件的另一个属性。
package My::Module;
use Moose;
use Config::Auto;
has 'config'=>(isa=>'HashRef[Str]',is=>'rw',required=>1);
has 'config_file'=>(isa=>'Str',is=>'ro');
around BUILDARGS=>sub
{
my $orig=shift;
my $class=shift;
my $args=shift; #currently {config_file=>'/path/to/file/config_file.conf'} (or whatever)
#make sure we've been passed a config file
confess "No config file found in BUILDARGS" unless defined $args->{config_file};
#Now, we open the user-specified config file via Config::Any
my $ca=Config::Auto->new(source=>$args->{config_file},format=>"colon");
my $parsed=$ca->parse; #hash reference containing the parsed data.
#Now, we add this to our arguments that will become our attributes:
$args->{config}=$parsed;
return $class->$orig($args);
}
no Moose;
1;
要实现BUILDARGS
的主要内容是它需要以下参数:类的名称和原始构造函数(传递给Moose::Object
)然后传递给构造函数的任何其他参数。所以,如果你打电话
my $mm=My::Module->new({config_file=>"/path/to/file/file.conf"});
然后,在BUILDARGS
中,我们最初有
$args=={config_file=>"/path/to/file/file.conf"}
但是在解析文件并添加$parsed
哈希引用之后,它变成了
$args=={config_file=>"/path/to/file/file.conf",config=>{server=>"mozilla.org",protocol=>"HTTP",...}}
等等。
在my $cfg = Config::Auto::parse($args);
内写BUILDARGS
,你试图将config_file
参数传递给Config::Auto
中的解析器,它不知道该怎么做做它。
答案 1 :(得分:1)
BUILDARGS
只是在构造开始时挂钩构造函数的一种方法。作为参考,construction section of the manual可能有助于您理解。
Jack Maney的回答非常好。基于他使用config_file
属性的建议,这里有一个使用lazy builder的替代方案。就个人而言,我更喜欢这些建筑物,因为代码稍微简单一些。构建器用于设置属性的默认值。你需要使它变得懒惰,因为构建属性取决于另一个属性(在本例中为config_file
),以确保完成对象的构造并设置了属性。
package DART::Setup;
use namespace::autoclean;
use Moose;
use MooseX::FileAttribute;
use Config::Auto;
# use MooseX::FileAttribute (optional) to enforce that the file actually exists
# - just a shortcut to remove some boilerplate code if you want
has_file 'config_file' => (
is => 'ro',
must_exist => 1,
required => 1,
);
has 'config' => (
isa => 'HashRef[Str]',
is => 'ro',
# disallow this attribute to be set by the constructor
init_arg => undef,
# cause this attribute to be set up after construction
lazy => 1,
builder => '_build_config',
# or alternatively, use 'default' instead of 'builder'
# (but it still needs to be lazy)
#default => sub { Config::Auto::parse( shift->config_file ) },
);
sub _build_config {
my ( $self ) = @_;
my $config = Config::Auto::parse( $self->config_file );
return $config;
}