Subclassing problems with relationships

[prev] [thread] [next] [Date index for 2004/06/30]

From: Mark Hughes
Subject: Subclassing problems with relationships
Date: 08:40 on 30 Jun 2004
This is a multi-part message in MIME format.
--------------010400070700060308070404
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

I'm trying to subclass our Class::DBI classes to allow us to run lots of 
slightly different versions of our application for different customers 
on one server. However we've come across a couple of problems with 
relationships.

(i) Adding a new relationship to the subclass seems to impact it's 
parent. For example if CD has a artist_id Artist, if we were to add a 
subclass of CD, ShopA::CD which has an artist_id ShopA::Artist then the 
CD artist_id also changes it's foreign class to ShopA::Artist.

(ii) ShopA::Artist can't retrieve ShopA::CD through a cds method as it 
is the same one that Artist / CD uses. This is due to a line in 
Class::DBI::Relationship

$class->can($accessor)
and return $class->_carp("$accessor method already exists in $class\n");

which we patch to be

defined &{"$class\::$accessor"}
and return $class->_carp("$accessor method already exists in $class\n");

However we still get the same problem of Artist->cds returning 
ShopA::CD. It seems that the accessor is the unique key for the 
relationship and if one exists in a subclass then that will be changed 
rather than creating a new one.

I've attached a simple example script which uses SQLite to show these 
issues. Are we doing something fundamentally wrong / is there a better 
way to do this ?

Cheers,
Mark.

--------------010400070700060308070404
Content-Type: text/x-perl;
 name="test.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="test.pl"

use strict;
use warnings;

package Data;
use base 'Class::DBI';
use File::Temp qw/tempfile/;
my (undef, $DB) = tempfile();
my @DSN = ("dbi:SQLite:dbname=$DB", '', '', { AutoCommit => 1 });
END { unlink $DB if -e $DB }
__PACKAGE__->connection(@DSN);

package CD;
use base 'Data';
__PACKAGE__->table('cd');
__PACKAGE__->columns(All => qw/id artist_id title/);
__PACKAGE__->has_a(artist_id => 'Artist');

package Artist;
use base 'Data';
__PACKAGE__->table('artist');
__PACKAGE__->columns(All => qw/id name/);
__PACKAGE__->has_many(cds => 'CD');

package ShopA::CD;
use base 'CD';
__PACKAGE__->table('shopa_cd');
__PACKAGE__->has_a(artist_id => 'ShopA::Artist');

package ShopA::Artist;
use base 'Artist';
__PACKAGE__->table('shopa_artist');
__PACKAGE__->has_many(cds2 => 'ShopA::CD');

package Main;

Data->db_Main->do(qq{
	CREATE TABLE cd (
		id int, 
		artist_id int, 
		title char(50)
	)
});

Data->db_Main->do(qq{
	CREATE TABLE shopa_cd (
		id int, 
		artist_id int, 
		title char(50)
	)
});

Data->db_Main->do(qq{
	CREATE TABLE artist (
		id int, 
		name char(50)
	)
});

Data->db_Main->do(qq{
	CREATE TABLE shopa_artist (
		id int, 
		name char(50)
	)
});

Artist->create({'id' => 1, name=>'Pixies'});
CD->create({'id' => 1, 'artist_id' => 1, title=>'Doolittle'});
ShopA::Artist->create({'id' => 1, name=>'Chikinki'});

my $cd = CD->retrieve(1);
printf("%s by %s\n",$cd->title,$cd->artist_id->name);

printf("CD meta info has a foreign class of %s\n",
	CD->meta_info('has_a' => 'artist_id')->foreign_class);



--------------010400070700060308070404--

Subclassing problems with relationships
Mark Hughes 08:40 on 30 Jun 2004

Generated at 11:34 on 01 Dec 2004 by mariachi v0.52