Jeremy Leipzig
Jeremy Leipzig

Reputation: 1944

Why does Moose make_immutable kill this script?

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();

Using perl 5.8.8 and Moose 2.0205

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

Upvotes: 1

Views: 248

Answers (1)

cjm
cjm

Reputation: 62109

You've defined the _sql_lib attribute twice, once saying isa Str and once saying it handles methods (which a Str doesn't), but that's not the problem you're talking about.

The main problem is that you didn't define _sql_lib with lazy => 1. Any attribute whose builder (or default) depends on other attributes of the object must be lazy, because Moose doesn't guarantee the order in which attributes are assigned values during object construction.

# 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',
    },
);

The reason that make_immutable brings out the bug is that calling it generates a different constructor for your class, which happens to initialize the attributes in a different order.

Upvotes: 3

Related Questions