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
- writable and updateable--transparently.
+ transparently writable.
- This is accomplished through the use of stored functions that map
+ This is accomplished through the use of stored procedures that map
changes written to the view to changes to the underlying concrete
tables.
has password
}
- class Investor isa User {
+ class Investor extends User {
has dollars
}
HOW?
There is a third strategy implemented here. Make the database do more of
- the work. It'll save us some typing and it'll make for more expressive
- code. What if we could do this:
+ the work: hide the nasty bits so we don't have to handle them unless we
+ really want to. It'll save us some typing and it'll make for more
+ expressive code. What if we could do this:
my $new_investor = $schema->resultset('Investor')->create(
name => $args->{name},
dollars => $args->{dollars},
);
- And have it Just Work? The user ( {name => $args->{name}, password =>
- $args->{password} } ) should be created transparently, and the use of
- either user or investor in your code should require no special handling.
- Deleting and updating $new_investor should also delete or update the
- user row.
+ And have it Just Work? The user...
+
+ {
+ name => $args->{name},
+ password => $args->{password},
+ }
+
+ should be created behind the scenes, and the use of either user or
+ investor in your code should require no special handling. Deleting and
+ updating $new_investor should also delete or update the user row.
It does. User and investor are both views, their concrete tables
abstracted away behind a set of rules and triggers. You would expect the
DELETE FROM _investor_table WHERE ("id" = ?);
DELETE FROM _user_table WHERE ("id" = ?);
+METHODS
+ new MTI find the parents, if any, of your resultset class and adds them
+ to the list of parent_sources for the table.
+
+ add_additional_parents
+ Continuing with coffee:
+
+ __PACKAGE__->result_source_instance->add_additional_parents(
+ qw/
+ MyApp::Schema::Result::Beverage
+ MyApp::Schema::Result::Liquid
+ /
+ );
+
+ This just lets you manually add additional parents beyond the ones
+ MTI finds.
+
+ add_additional_parent
+ __PACKAGE__->result_source_instance->add_additional_parent(
+ MyApp::Schema::Result::Beverage
+ );
+
+ You can also add just one.
+
+ attach_additional_sources
+ MTI takes the parents' sources and relationships, creates new
+ DBIx::Class:Table object from them, and registers this as a new,
+ raw, source in the schema, e.g.,
+
+ use MyApp::Schema;
+
+ print STDERR map { "$_\n" } MyApp::Schema->sources;
+
+ # Coffee
+ # Beverage
+ # Liquid
+ # Sumatra
+ # Raw::Sumatra
+
+ Raw::Sumatra will be used to generate the view.
+
+ view_definition
+ This takes the raw table and generates the view (and stored
+ procedures) you will use.
+
AUTHOR
Matt S. Trout, <mst@shadowcatsystems.co.uk>
<ul>
- <li><a href="#name">NAME</a></li>
<li><a href="#synopsis">SYNOPSIS</a></li>
<li><a href="#why">WHY?</a></li>
<li><a href="#how">HOW?</a></li>
+ <li><a href="#methods">METHODS</a></li>
<li><a href="#author">AUTHOR</a></li>
<ul>
<p>
</p>
-<hr />
-<h1><a name="name">NAME</a></h1>
-<p>DBIx::Class::ResultSource::MultipleTableInheritance -- Use multiple tables to define your classes</p>
-<p>
-</p>
-<hr />
<h1><a name="synopsis">SYNOPSIS</a></h1>
<pre>
{
$VAR1 = 'id';
$VAR2 = 'flavor';
$VAR3 = '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>writable</strong> and updateable--transparently.</p>
-<p>This is accomplished through the use of stored functions that map changes written to the view to changes to the underlying concrete tables.</p>
+<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 />
has password
}</pre>
<pre>
- class Investor isa User {
+ class Investor extends User {
has dollars
}</pre>
<p>Good idea, but how to put this into code?</p>
</p>
<hr />
<h1><a name="how">HOW?</a></h1>
-<p>There is a third strategy implemented here. Make the database do more of the work. It'll save us some typing and it'll make for more expressive code. What if we could do this:</p>
+<p>There is a third strategy implemented here. Make the database do more of the work: hide the nasty bits so we don't have to handle them unless we really want to. It'll save us some typing and it'll make for more expressive code. What if we could do this:</p>
<pre>
my $new_investor = $schema->resultset('Investor')->create(
name => $args->{name},
dollars => $args->{dollars},
);
-And have it Just Work? The user ( {name => $args->{name}, password => $args->{password} } ) should be created transparently, and the use of either user or investor in your code should require no special handling. Deleting and updating $new_investor should also delete or update the user row.</pre>
+And have it Just Work? The user...</pre>
+<pre>
+ {
+ name => $args->{name},
+ password => $args->{password},
+ }</pre>
+<p>should be created behind the scenes, and the use of either user or investor in your code should require no special handling. Deleting and updating $new_investor should also delete or update the user row.</p>
<p>It does. User and investor are both views, their concrete tables abstracted away behind a set of rules and triggers. You would expect the above DBIC create statement to look like this in SQL:</p>
<pre>
INSERT INTO investor ("name","password","dollars") VALUES (...);</pre>
<pre>
DELETE FROM _investor_table WHERE ("id" = ?);
DELETE FROM _user_table WHERE ("id" = ?);</pre>
-<p></p>
+<p>
+</p>
+<hr />
+<h1><a name="methods">METHODS</a></h1>
+<dl>
+<dt><strong><a name="new" class="item">new</a></strong></dt>
+
+<dd>
+<p>MTI find the parents, if any, of your resultset class and adds them to the list of parent_sources for the table.</p>
+</dd>
+<dt><strong><a name="add_additional_parents" class="item">add_additional_parents</a></strong></dt>
+
+<dd>
+<p>Continuing with coffee:</p>
+<pre>
+ __PACKAGE__->result_source_instance->add_additional_parents(
+ qw/
+ MyApp::Schema::Result::Beverage
+ MyApp::Schema::Result::Liquid
+ /
+ );</pre>
+<p>This just lets you manually add additional parents beyond the ones MTI finds.</p>
+</dd>
+<dt><strong><a name="add_additional_parent" class="item">add_additional_parent</a></strong></dt>
+
+<dd>
+<pre>
+ __PACKAGE__->result_source_instance->add_additional_parent(
+ MyApp::Schema::Result::Beverage
+ );</pre>
+<p>You can also add just one.</p>
+</dd>
+<dt><strong><a name="attach_additional_sources" class="item">attach_additional_sources</a></strong></dt>
+
+<dd>
+<p>MTI takes the parents' sources and relationships, creates new DBIx::Class:Table object from them, and registers this as a new, raw, source in the schema, e.g.,</p>
+<pre>
+ use MyApp::Schema;</pre>
+<pre>
+ print STDERR map { "$_\n" } MyApp::Schema->sources;</pre>
+<pre>
+ # Coffee
+ # Beverage
+ # Liquid
+ # Sumatra
+ # Raw::Sumatra</pre>
+<p>Raw::Sumatra will be used to generate the view.</p>
+</dd>
+<dt><strong><a name="view_definition" class="item">view_definition</a></strong></dt>
+
+<dd>
+<p>This takes the raw table and generates the view (and stored procedures) you will use.</p>
+</dd>
+</dl>
<p>
</p>
<hr />
__PACKAGE__->mk_group_accessors(simple => qw(parent_source additional_parents));
+# how this works:
+#
+# On construction, we hook $self->result_class->result_source_instance
+# if present to get the superclass' source object
+#
+# When attached to a schema, we need to add sources to that schema with
+# appropriate relationships for the foreign keys so the concrete tables
+# get generated
+#
+# We also generate our own view definition using this class' concrete table
+# and the view for the superclass, and stored procedures for the insert,
+# update and delete operations on this view.
+#
+# deploying the postgres rules through SQLT may be a pain though.
+
method new ($class: @args) {
my $new = $class->next::method(@args);
my $rc = $new->result_class;
1;
__END__
-
-# how this works:
-#
-# On construction, we hook $self->result_class->result_source_instance
-# if present to get the superclass' source object
-#
-# When attached to a schema, we need to add sources to that schema with
-# appropriate relationships for the foreign keys so the concrete tables
-# get generated
-#
-# We also generate our own view definition using this class' concrete table
-# and the view for the superclass, and stored procedures for the insert,
-# update and delete operations on this view.
-#
-# deploying the postgres rules through SQLT may be a pain though.
-
-=encoding utf-8
-
=head1 NAME
DBIx::Class::ResultSource::MultipleTableInheritance -- Use multiple tables to define your classes
=head1 SYNOPSIS
-
{
package MyApp::Schema::Result::Coffee;
$VAR3 = '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>.
-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<transparentlt writable>.
+This is accomplished through the use of stored procedures that map changes written to the view to changes to the underlying concrete tables.
-This is accomplished through the use of stored functions that map changes written to the view to changes to the underlying concrete tables.
=head1 WHY?
has password
}
- class Investor isa User {
+ class Investor extends User {
has dollars
}
One can cope well with the second strategy, and it seems to be the most popular smart choice.
+
=head1 HOW?
-There is a third strategy implemented here. Make the database do more of the work. It'll save us some typing and it'll make for more expressive code. What if we could do this:
+There is a third strategy implemented here. Make the database do more of the work: hide the nasty bits so we don't have to handle them unless we really want to. It'll save us some typing and it'll make for more expressive code. What if we could do this:
my $new_investor = $schema->resultset('Investor')->create(
name => $args->{name},
dollars => $args->{dollars},
);
-And have it Just Work? The user ( {name => $args->{name}, password => $args->{password} } ) should be created transparently, and the use of either user or investor in your code should require no special handling. Deleting and updating $new_investor should also delete or update the user row.
+And have it Just Work? The user...
+
+ {
+ name => $args->{name},
+ password => $args->{password},
+ }
+
+should be created behind the scenes, and the use of either user or investor in your code should require no special handling. Deleting and updating $new_investor should also delete or update the user row.
It does. User and investor are both views, their concrete tables abstracted away behind a set of rules and triggers. You would expect the above DBIC create statement to look like this in SQL:
DELETE FROM _user_table WHERE ("id" = ?);
-
+=head1 METHODS
+
+=over
+
+=item new
+
+
+MTI find the parents, if any, of your resultset class and adds them to the list of parent_sources for the table.
+
+
+=item add_additional_parents
+
+
+Continuing with coffee:
+
+ __PACKAGE__->result_source_instance->add_additional_parents(
+ qw/
+ MyApp::Schema::Result::Beverage
+ MyApp::Schema::Result::Liquid
+ /
+ );
+
+This just lets you manually add additional parents beyond the ones MTI finds.
+
+=item add_additional_parent
+
+ __PACKAGE__->result_source_instance->add_additional_parent(
+ MyApp::Schema::Result::Beverage
+ );
+
+You can also add just one.
+
+=item attach_additional_sources
+
+MTI takes the parents' sources and relationships, creates new DBIx::Class:Table object from them, and registers this as a new, raw, source in the schema, e.g.,
+
+ use MyApp::Schema;
+
+ print STDERR map { "$_\n" } MyApp::Schema->sources;
+
+ # Coffee
+ # Beverage
+ # Liquid
+ # Sumatra
+ # Raw::Sumatra
+Raw::Sumatra will be used to generate the view.
+=item view_definition
+This takes the raw table and generates the view (and stored procedures) you will use.
+=back
=head1 AUTHOR
'parent rel points to raw parent'
);
-warn Dumper $raw_bar->_columns;
+my $foo = MTITest->source('Foo');
+my $bar = MTITest->source('Bar');
-warn Dumper $raw_bar->_relationships;
+is_deeply(
+ [ $foo->columns ],
+ [ qw(id a) ],
+ 'Columns for mti foo are still the same: id a'
+);
+
+
+is_deeply(
+ [ $bar->columns ],
+ [ qw(id a words b) ],
+ 'Columns for mti bar now contain those of foo and the mixin: id a words b'
+);
+
+
+#warn Dumper $raw_bar->_columns;
+
+#warn Dumper $raw_bar->_relationships;
-warn Dumper(MTITest->source('JustATable')->_relationships);
+#warn Dumper(MTITest->source('JustATable')->_relationships);
--
-- Created by SQL::Translator::Producer::PostgreSQL
--- Created on Sat Apr 10 11:29:16 2010
+-- Created on Sun Apr 11 11:56:23 2010
--
--
-- Table: just_a_table