How do I override autogenerated accessors in Perl's Class::DBI?
Question
I followed the example at http://wiki.class-dbi.com/wiki/Overriding_autogenerated_accessors
I want to modify the URL before it is inserted to the database:
package Hosting::Company;
use base 'Class::DBI';
my $class = __PACKAGE__;
$class->table('Companies');
$class->columns(Primary => 'CompanyId');
$class->columns(Others => qw/Name Url Comment/);
sub Url {
my $self = shift;
# modify URL.
if (@_) {
$_[0] = 'aaaaaaaaaaaa';
# return $self->_Url_accessor('aaaaaaaaaaaa'); - doesn't work either
}
# Back to normal Class::DBI
return $self->_Url_accessor(@_);
}
But it doesn't work:
my $company = Hosting::Company->insert({ Name => 'Test', Url => 'http://http://url' });
print $company->Url, "\n";
Shows:
http://http://url
I wish the Class:DBI mailing list were still alive!
Solution
Overriding an accessor does not change insert
. The best way to handle data normalization is to override normalize_column_values()
. But Manni is right, your accessor is busted.
PS The CDBI mailing list is still active, just hasn't seen much posting. Most have moved on to DBIx::Class.
OTHER TIPS
In you URL accessor, you check whether a parameter was passed to that method. But you aren't passing anyhting in so the accessor will do nothing but call _Url_accessor(). You should probably call _Url_accessor first and then modify the result:
sub Url {
my $self = shift;
# Was there a param passed in?
if ( @_ ) {
# Do you really want to modify it here?
return $self->_Url_accessor(@_);
}
else {
my $url = $self->_Url_accessor();
# mangle result here:
$url = 'aaaaaaaaa';
return $url;
}
}
If you want to change the URL before it even goes in the database, I guess you must provide a normalize_column_values in your class and this will be called each time an insert is made.