Vague thoughts about is_a and might_be relationships
[prev]
[thread]
[next]
[Date index for 2004/08/18]
I've been thinking about how Class::DBI might work with table
inheritance recently and briefly experimented with writing a custom
relationship for this. This is partly a feature request, and partly an
attempt to document what I've done so far.
Imagine I have a group of pets. My pets may be cats or dogs.
I could model this scenario in SQL roughly as follows:
CREATE TABLE cats (
id INTEGER PRIMARY KEY,
name VARCHAR(255),
owner INTEGER,
basket INTEGER
);
CREATE TABLE dogs (
id INTEGER PRIMARY KEY,
name VARCHAR(255),
owner INTEGER,
kennel INTEGER
);
And with Class::DBI as follows:
package Pet::Cat;
use base 'Class::DBI::SQLite';
__PACKAGE__->set_up_table('cats');
__PACKAGE__->has-a(owner => 'Person');
__PACKAGE__->has_a(basket => 'House::Basket');
package Pet::Dog;
use base 'Class::DBI::SQLite';
__PACKAGE__->set_up_table('dogs');
__PACKAGE__->has-a(owner => 'Person');
__PACKAGE__->has_a(kennel => 'House::Kennel');
This works fine, but if I want to retrieve a list of all the pets I own,
I need to know all the classes that represent pets.
I would like to do something like:
CREATE TABLE pets (
id INTEGER PRIMARY KEY,
name VARCHAR(255),
owner INTEGER
);
CREATE TABLE cats (
id INTEGER PRIMARY KEY,
basket INTEGER
);
CREATE TABLE dogs (
id INTEGER PRIMARY KEY,
kennel INTEGER
);
package Pet;
use base 'Class::DBI::SQLite';
__PACKAGE__->set_up_table('pets');
__PACKAGE__->might_be('Pet::Cat');
__PACKAGE__->might_be('Pet::Dog');
package Pet::Cat;
use base 'Class::DBI::SQLite';
__PACKAGE__->set_up_table('cats');
__PACKAGE__->is_a('Pet');
# Pet::Dog works the same way as Pet::Cat
The new things here are the is_a and might_be relationships. These
specify inheritance but do so in a non-Perlish way: We don't 'use base'
for inheritance to avoid set_up_table and relationship specification
methods being called twice. I think this makes sense.
The existing might_have relationship works very much like how I imagine
might_be working. I wonder if it lacks anything.
The is_a relationship would behave somewhat like a cross between has_a
and might_have. If an object exists in the subclass (eg. Pet::Cat) it
must also exist in the superclass (Pet), as per a has_a relationship.
However, I imagine is_a having a 'methods' method like might_have's:
allowing direct access to superclass attributes, eg. $cat->name instead
of $cat->id->name.
Also, when using the subclass's create method, eg. Pet::Cat->create, the
underlying Pet information must be created first, to ensure a
one-to-one mapping between id fields.
Finally, it would be neat if Pet objects were reblessed (using a select
trigger?) into a subclass if appropriate. If I run:
my @pets = Pet->retrieve_all;
print $_->name, ' is a ', ref($_), ".\n" foreach @pets;
I would expect output like:
Tiddles is a Pet::Cat
Fido is a Pet::Dog
Bubbles is a Pet
where pets that don't belong in any subclass aren't reblessed.
Does any of this sound sensible? Have I missed anything? Does anyone
have useful advice on relationships that might help me? In a Class::DBI
context, of course. Ahem.
Thanks,
Tom
|
Vague thoughts about is_a and might_be relationships
Tom Hukins 14:22 on 18 Aug 2004
|