DBIx-Class-ResultSource-MultipleTableInheritance

 view release on metacpan or  search on metacpan

README  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."

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
    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.

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.960 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )