Perl Moose - 从配置文件加载值时有什么参数?

时间:2012-03-20 00:29:41

标签: perl moose

在我之前的问题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";
}

我是否正确理解了这一点?

2 个答案:

答案 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;
}