[CDBI] Class::DBI and DESTROY

Steven Mackenzie steven.mackenzie at aptile.co.uk
Thu Nov 10 13:15:49 GMT 2005


I am using the ActiveState Class::DBI (version 0.96) with Perl 5.8.7.

I have tried to add some new methods to one of my Class::DBI classes,
but they require state to be preserved for each instance. I didn't want
to just stash my state in the cdbi object hash (it didn't work anyway),
so I'm using a variation of "Perl Best Practices" inside out classes.

State for each instance (db row) is preserved in a class hash, and then
cleaned up when finished with a DESTROY method. But DESTROY is being
called far more often than I expected. (And more often in my Perl 5.8.7
install than my colleagues 5.8.4 install). It seems like the Class::DBI
objects are being torn down even though I still hold references to them.
The really odd thing is that the references seem to remain valid -- I
can still use the reference to call Class::DBI methods, even though the
DESTROY was called. Clearly I am not understanding something.

Can anyone share some insight in to my problem (why is DESTROY being
called so often?), or offer a better approach for me?

As an example, imagine I need to write index cards for my CD collection.
Easy listening CDs need the cards printed in large type, and classical
CDs need to be printed on two cards to make room for the sleeve notes,
so each CD object returned is configured with a special card writer
object. To do this, I have added some lines like these to my Music::CD
class:

# specialized card writer objects for each CD
my %card_writer_of; # keyed by cdid

sub DESTROY
{
 my ($self) = @_;
 my $cd_ref = $self->cdid;
 # ... not Scalar::Util::refaddr( $self ) because
 #     the object refaddr changes -- use the DB key
 #     for this row to identify this object instance.

 delete $card_writer_of{ $cd_ref };

 $self->SUPER::DESTROY();
}

# Get or set card_writers for this cd
sub writer
{
  my ($self, $writer);

  my $cd_ref = $self->cdid;

  if( defined $writer )
  { #set
    $card_writer_of{ $cd_ref } = $writer;
    return $self;
  }
  else
  { #get
    return $card_writer_of{ $cd_ref };
  }
}

# use the configured card writer to write an index card for this CD
sub write
{
  my ($self, $filename) = @_;
  my $cd_ref = $self->cdid;

  my $writer = $card_writer_of{ $cd_ref };
  # Eeek - this is usually undef by the time I call this,
  # because the card_writer has been flushed away by a
  # call to DESTROY.

  $writer->write($filename);
}






More information about the ClassDBI mailing list