DBIx-Class-ResultSource-MultipleTableInheritance
view release on metacpan or search on metacpan
lib/DBIx/Class/ResultSource/MultipleTableInheritance.pm view on Meta::CPAN
This only works with PostgreSQL at the moment. It has been tested with
PostgreSQL 9.0, 9.1 beta, and 9.1.
There is one additional caveat: the "parent" result classes that you
defined with this resultsource must have one primary column and it must
be named "id."
=head1 SYNOPSIS
{
package Cafe::Result::Coffee;
use strict;
use warnings;
use parent 'DBIx::Class::Core';
use aliased 'DBIx::Class::ResultSource::MultipleTableInheritance'
=> 'MTI';
__PACKAGE__->table_class(MTI);
__PACKAGE__->table('coffee');
__PACKAGE__->add_columns(
"id", { data_type => "integer" },
"flavor", {
data_type => "text",
default_value => "good" },
);
__PACKAGE__->set_primary_key("id");
1;
}
{
package Cafe::Result::Sumatra;
use parent 'Cafe::Result::Coffee';
__PACKAGE__->table('sumatra');
__PACKAGE__->add_columns( "aroma",
{ data_type => "text" }
);
1;
}
...
my $schema = Cafe->connect($dsn,$user,$pass);
my $cup = $schema->resultset('Sumatra');
print STDERR Dwarn $cup->result_source->columns;
"id"
"flavor"
"aroma"
..
Inherit from this package and you can make a resultset class from a view, but
that's more than a little bit misleading: the result is B<transparently
writable>.
This is accomplished through the use of stored procedures that map changes
written to the view to changes to the underlying concrete tables.
=head1 WHY?
In many applications, many classes are subclasses of others. Let's say you
have this schema:
# Conceptual domain model
class User {
has id,
has name,
has password
}
class Investor {
has id,
has name,
has password,
has dollars
}
That's redundant. Hold on a sec...
class User {
has id,
has name,
has password
}
class Investor extends User {
has dollars
}
Good idea, but how to put this into code?
One far-too common and absolutely horrendous solution is to have a "checkbox"
in your database: a nullable "investor" column, which entails a nullable
"dollars" column, in the user table.
create table "user" (
"id" integer not null primary key autoincrement,
"name" text not null,
"password" text not null,
"investor" tinyint(1),
"dollars" integer
);
Let's not discuss that further.
A second, better, solution is to break out the two tables into user and
investor:
create table "user" (
"id" integer not null primary key autoincrement,
"name" text not null,
"password" text not null
( run in 2.446 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )