Почему Moose make_immutable убивает этот скрипт? - PullRequest
1 голос
/ 19 октября 2011
package testDB;
use Moose;
use Carp;
use SQL::Library;

has 'lib' => (#FOLDBEG
    is => 'rw',
    isa => 'Str',
    default => 'default',
    trigger => \&_sql_lib_builder,
);#FOLDEND

has 'lib_dir' => (#FOLDBEG
    is => 'ro',
    isa => 'Str',
    default => '/SQL',
);#FOLDEND

has '_sql_lib' => (#FOLDBEG                                                                                                                            
   builder => '_sql_lib_builder',
    is => 'rw',
    isa => 'Str',
);

has '_sql_lib' => (#FOLDBEG                                                                                                                            
    builder => '_sql_lib_builder',
    is => 'rw',
           handles => {
        get_sql => 'retr',
        get_elements => 'elements',
    },
);

sub _sql_lib_builder {
    my ($self, $lib) = shift();
    $self->lib() or die("I am unable to get a lib.");
    $lib = $self->lib unless $lib;


    my $lib_dir = $self->lib_dir;
    print $lib_dir."\n";

    my $lib_file = $lib_dir . '/' . $lib . '.sql';

    unless (-e $lib_file ) {
        confess "SQL library $lib does not exist";
    }

    my $library = new SQL::Library { lib => $lib_file };

    $self->_sql_lib($library);

}#FOLDEND

__PACKAGE__->meta->make_immutable;

my $tdb=testDB->new();

Использование Perl 5.8.8 и Moose 2.0205

$ perl testDB.pl 
I am unable to get a lib. at testDB.pl line 35.

1 Ответ

3 голосов
/ 19 октября 2011

Вы определили атрибут _sql_lib дважды, однажды сказав isa Str и однажды сказав, что он обрабатывает методы (а Str нет), но вы не об этом говорите.

Основная проблема в том, что вы не определили _sql_lib с lazy => 1.Любой атрибут, чей конструктор (или default) зависит от других атрибутов объекта, должен быть lazy, поскольку Moose не гарантирует порядок, в котором атрибутам присваиваются значения во время построения объекта.

# REMOVE THIS:
#has '_sql_lib' => (#FOLDBEG                                 
#   builder => '_sql_lib_builder',
#    is => 'rw',
#    isa => 'Str',
#);

has '_sql_lib' => (#FOLDBEG                                 
    builder => '_sql_lib_builder',
    is => 'rw',
    lazy => 1,                       # ADD THIS LINE
    handles => {
        get_sql => 'retr',
        get_elements => 'elements',
    },
);

Причина, по которой make_immutable выявляет ошибку, заключается в том, что при ее вызове генерируется другой конструктор для вашего класса, который инициализирует атрибуты в другом порядке.

...