I was wondering how you design your base classes for DBIC result(set) classes. I think it’s a good idea both in terms of startup speed and ease of use to not use DBIx::Class as base of your result classes but use a custom one instead. The same applies for the resultset classes. Here is how I designed my DBIC classes:
Make sure you use load_namespacesin MySchema.pm!
Directory structure:
MySchema.pm
MySchema/
Base/
Result.pm
ResultSet.pm
Result/
User.pm
ResultSet/
User.pm
This has the advantage that the base classes in base are not being loaded. All classes in Result use MySchema::Base::Result as their base class. Classes in ResultSet use MySchema::Base::ResultSet respectively.
My current result base class looks like this:
package MySchema::Base::Result; use strict; use warnings; use base 'DBIx::Class'; __PACKAGE__->load_components(qw(RandomColumns InflateColumn::FS TimeStamp Core)); __PACKAGE__->table('dummy'); __PACKAGE__->add_columns( id => { data_type => 'character', is_random => {size => 10, set => ['a'..'z','A'..'Z'], check => 1}, size => 10, }, created_on => { data_type => 'timestamp with time zone', set_on_create => 1, is_nullable => 1 }, updated_on => { data_type => 'timestamp with time zone', set_on_create => 1, set_on_update => 1, is_nullable => 1 }); __PACKAGE__->set_primary_key('id'); sub sqlt_deploy_hook { my ($self, $sqlt_table) = @_; map { $sqlt_table->drop_constraint($_) if $_->type eq "FOREIGN KEY" } $sqlt_table->get_constraints; } 1;
So what is going on here?
First I use load_components to load all the components which are valuable to all of my result classes. Since I always use a random combination of characters for the primary key column id I load RandomColumns. InflateColumn::FS makes sure that any BLOB is stored on the file system rather than in the database. TimeStamp can set columns to the current time on either update or create. It also loads InflateColumn::DateTime which is used to inflate any date or time columns to a DateTime object.
You need to define a table name, otherwise DBIC fails to compile. This table will never be created or seen in any of your result classes as long as you overwrite it in each class. So just name it dummy or something and you are good.
Next I create a couple of columns which should be avaiable on all result classes. My primary key is always called id so create that column for all my classes. To use the RandomColumns component you have to add that is_random line to the column definition. This will create a random 10-byte long string. Since I’m a little bit paranoid about collision I set the check parameter so the component checks before inserting a new row if a column with that id is already there. Although this is very unlikely because there are 52^10 combinations, quite a lot…
The created_on and updated_on columns use the features of TimeStamp to set the time when the record was created or updated respectively. timestamp with time zone is a PostgreSQL specific column. You might need to the correct data type of your dbms.
I use SQL::Translator, DBIx::Class::Schema::Versioned and a few lines of code to deploy and update my database schema. Foreign key constraints on the database slow things down and DBIC handles them anyway so I decided to drop them from the SQL::Translator output. this is done in the sqlt_deploy_hook method.

