[Dbix-class] New cookbook recipe: inheriting from result classes

Sebastian Willert willert at gmail.com
Sat Jun 24 02:29:06 CEST 2006


Hi all,

as promised on #dbix-class earlier today, I wrote some POD to explain
how one can inherit from result classes (this approach works for the
current dev releases only).

Feel free to edit, criticize, share and include anywhere.

Cheers,
  Sebastian

---

=head1 NAME

DBIx::Class::Manual::Cookbook - Miscellaneous recipes

=head1 RECIPES

=head2 Inheritance

=head3 Upgrading result source classes

In some edge cases it might be useful (or even necessary if enforced
by local policies) to use a class hierarchy instead of a monolithic
result
source class.

In this recipe we will assume you have lightweight schema but need to
pull in some very heavy or inconvenient stuff for some perspectives on
your data. You wouldn't want them in your bases sources so we are just
going to create a plain schema at first

  package Foo::Schema::Recipe;
  use base 'DBIx::Class';
  __PACKAGE__->load_components("PK::Auto", "Core");
  __PACKAGE__->table("recipe");
  __PACKAGE__->add_columns("id", "name", "description");
  __PACKAGE__->set_primary_key("id");
  __PACKAGE__->has_many
    ( ingredients => qw/Foo::Schema::Ingredients/ => qw/recipe/);

  package Foo::Schema::Ingredient;
  use base 'DBIx::Class';
  __PACKAGE__->load_components("PK::Auto", "Core");
  __PACKAGE__->table("ingredient");
  __PACKAGE__->add_columns( "id", "recipe", "name", "quantity" );
  __PACKAGE__->set_primary_key("id");
  __PACKAGE__->belongs_to( recipe => qw/Foo::Schema::Recipe/ );

  package Foo::Schema;
  use base 'DBIx::Class::Schema';
  __PACKAGE__->load_classes( qw/Recipe Ingredient/ );

  1;

Now for the trickier part: inheriting from the schema classes has a
few caveats but lets get the boilerplate code out of the way first
(I've  included C<Log::Log4perl> so you get an idea what I meant
with inconvenient, by the way).

  package Bar::Recipe;
  use base qw(Foo::Schema::Recipe);
  use Log::Log4perl;
  my $log = Log::Log4perl::get_logger( __PACKAGE__ );

So far, we didn't do anything unexpected, but C<DBIx::Class::Schema>
doesn't know anything about our new class. First of all we will have to
get a clone of the original source table class. Just setting the table
attribute again will achieve this.

  __PACKAGE__->table( __PACKAGE__->table );

Then we will have to declare a distinct moniker for our subclass. If
we don't do this, C<Bar::Recipe> will override all
C<Foo::Schema::Recipe>
result sets which can be desirable for quick'n'dirty hacks but is not
advisable otherwise.

  __PACKAGE__->source_name( 'HeavyRecipe' );

Finally we are all set to muck about the classes inner working to our
hearts content.

  __PACKAGE__->has_many
    ( Ingredients => qw/Bar::Ingredient/ => qw/recipe/);

Writing C<Bar::Ingredient> is left as an exercise to the reader. The
last thing to do is load the new classes into a schema. This can be
done in a standard way trough inheriting from C<Foo::Schema> or at
run-time via:

  $schema->load_classes({ Bar => [qw( Recipe Ingredient )] });

=cut






More information about the Dbix-class mailing list