views:

81

answers:

1

With the following (simplified) MySQL table definitions:

create table items (
    item_id         int unsigned auto_increment primary key,
    purchase_date   date
    ) engine = innodb;

create table computers (
    item_id         int unsigned primary key,
    processor_type  varchar(50),
    foreign key item_fk (item_id) references items (item_id) 
        on update restrict on delete cascade
    ) engine = innodb;

create table printers (
    item_id         int unsigned primary key,
    is_duplex       boolean,
    foreign key item_fk (item_id) references items (item_id) 
        on update restrict on delete cascade
    ) engine = innodb;

Being new to DBIx::Class, I would like to model an inheritance relationship between database entities (computers and printers both being items), but with the provided belongs_to relationship type, this seems to be awkward, because the association with the base class is not hidden, so one must still manually create entities for both classes, and access to base class attributes in the derived classes is different from accessing their own attributes.

Is there an elegant solution which would allow me to say:

$printer = $printer_rs->create({purchase_date => $date, is_duplex => 0});

or (on a fetched printer row):

$date = $printer->purchase_date;
$duplex = $printer->is_duplex;

?

+5  A: 

You can use the proxy attribute on a relationship to enable the accessors -- it's documented in add_relationship of DBIx::Class::Relationship::Base and you can use it with belongs_to like:

__PACKAGE__->belongs_to(
  'item' => 'MyApp::Schema::Item',
  'item_id',
  { proxy => [ qw/purchase_date/ ] }
);

which will make all of your Printer objects have purchase_date accessors that refer to the associated Item object.

As for create, you can't do it without overriding new_result, which is actually pretty easy. You just have to take advantage of the create-from-related behavior to turn

->create({
  is_duplex => 1,
  purchase_date => $dt,
})

into

->create({
  is_duplex => 1,
  item => {
    purchase_date => $dt,
  },
})

Or you could just foist the knowledge of what columns are in item off on your users and have them provide that hashref directly ;)

hobbs