DBIx-Class-ResultSource-MultipleTableInheritance
view release on metacpan or search on metacpan
README.html view on Meta::CPAN
<p>This only works with PostgreSQL at the moment. It has been tested with
PostgreSQL 9.0, 9.1 beta, and 9.1.</p>
<p>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."</p>
<p>
</p>
<hr />
<h1><a name="synopsis">SYNOPSIS</a></h1>
<pre>
{
package Cafe::Result::Coffee;</pre>
<pre>
use strict;
use warnings;
use parent 'DBIx::Class::Core';
use aliased 'DBIx::Class::ResultSource::MultipleTableInheritance'
=> 'MTI';</pre>
<pre>
__PACKAGE__->table_class(MTI);
__PACKAGE__->table('coffee');
__PACKAGE__->add_columns(
"id", { data_type => "integer" },
"flavor", {
data_type => "text",
default_value => "good" },
);</pre>
<pre>
__PACKAGE__->set_primary_key("id");</pre>
<pre>
1;
}</pre>
<pre>
{
package Cafe::Result::Sumatra;</pre>
<pre>
use parent 'Cafe::Result::Coffee';</pre>
<pre>
__PACKAGE__->table('sumatra');</pre>
<pre>
__PACKAGE__->add_columns( "aroma",
{ data_type => "text" }
);</pre>
<pre>
1;
}</pre>
<pre>
...</pre>
<pre>
my $schema = Cafe->connect($dsn,$user,$pass);</pre>
<pre>
my $cup = $schema->resultset('Sumatra');</pre>
<pre>
print STDERR Dwarn $cup->result_source->columns;</pre>
<pre>
"id"
"flavor"
"aroma"
..</pre>
<p>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 <strong>transparently
writable</strong>.</p>
<p>This is accomplished through the use of stored procedures that map changes
written to the view to changes to the underlying concrete tables.</p>
<p>
</p>
<hr />
<h1><a name="why">WHY?</a></h1>
<p>In many applications, many classes are subclasses of others. Let's say you
have this schema:</p>
<pre>
# Conceptual domain model</pre>
<pre>
class User {
has id,
has name,
has password
}</pre>
<pre>
class Investor {
has id,
has name,
has password,
has dollars
}</pre>
<p>That's redundant. Hold on a sec...</p>
<pre>
class User {
has id,
has name,
has password
}</pre>
<pre>
class Investor extends User {
has dollars
}</pre>
<p>Good idea, but how to put this into code?</p>
<p>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.</p>
<pre>
create table "user" (
"id" integer not null primary key autoincrement,
"name" text not null,
"password" text not null,
"investor" tinyint(1),
"dollars" integer
);</pre>
<p>Let's not discuss that further.</p>
<p>A second, better, solution is to break out the two tables into user and
investor:</p>
<pre>
create table "user" (
"id" integer not null primary key autoincrement,
"name" text not null,
"password" text not null
);</pre>
<pre>
create table "investor" (
"id" integer not null references user("id"),
"dollars" integer
( run in 1.103 second using v1.01-cache-2.11-cpan-5b529ec07f3 )