I know we all must often run into schema designs like the following:

## Column details removed for clarity
package MyApp::Schema::Result::Gender; {
        use base 'MyApp::Schema::Result';
        
        __PACKAGE__->table('gender');   
        __PACKAGE__->add_columns(qw/gender_id label/);
}

package MyApp::Schema::Result::Person; {
        use base 'MyApp::Schema::Result';

        __PACKAGE__->table('person');
        __PACKAGE__->add_columns(qw/person_id name fk_gender_id);

        __PACKAGE__->belongs_to(
                gender => 'MyApp::Schema::Gender',
                {'foreign.fk_gender_id' => 'self.fk_gender_id'}
        );
}

After all, this is type of normalization is a basic pattern.  However, as far 
as I know we don't have a good system for installing the necessary data at 
populate time.  What I mean here is that for the above database to be useful, 
you need some rows inserted into the 'gender' table, ie 'female', 'male', 
'transgendered', etc.

Things I've seen people do to work around this lack would include manually 
created SQL files to run post deployment, manually editing the sql generated by 
$storage->deploy, overloading deploy to run a set of ->create statements, or 
trying to use the Fixtures module.

All the above solutions work, but have severe lacking.  For example, all the 
solutions involving editing sql files fail to achieve the degree of database 
freedom DBIC offers out of the box.  Additionally, by not having DBIC itself 
aware of the lookup information, you lose out on the chance to apply roles to 
your classes based on the lookup in a clear an easy manner.  For example, I 
often have a 'state' table as a lookup normalization on a persons address.  
However, I also often have the need to apply special logic to people living in 
the state of California, since that state has a lot of special rules.  Right 
now this usually manifests itself as a lot of ugly conditional logic.  It would 
be really nice if DBIC itself could have enough awareness to apply components 
or roles at runtime when a row returned contain a particular lookup value.

Lastly, it would be great if this system could hook cleanly into the DBIC 
framework for doing database diffs.  That way if you had to alter something, 
like a list of Countries, for example, you'd get a head start on the generated 
sql between versions.

So here's my first go at attempting to create some syntax for this.  Yeah, 
there's a lot to do with it, but this is a start.  It's possible we'd rather 
have the lookup data encapsulated in a different class, just to keep the the 
class files clean.  Please your comments and suggestions very welcomed!

package MyApp::Schema::Result::Gender; {
        use base 'MyApp::Schema::Result';
        
        __PACKAGE__->components('Lookup');
        __PACKAGE__->table('gender');   
        __PACKAGE__->add_columns(
                gender_id => {
                        data_type => 'varchar', 
                        size => '36', 
                        is_nullable => 0, 
                },
                label => {
                        data_type => 'varchar',
                        size => '12',
                        is_nullable => 0,
                },
        );

        __PACKAGE__->set_primary_key('gender_id');
        __PACKAGE__->uuid_columns('gender_id');
        
        __PACKAGE__->lookup_unique_label('label');
        __PACKAGE__->populate_lookup(
                ['lookup'],
                ['male'],
                ['female],
                ['transgendered'],
                ['unknown'],
        );
}

package MyApp::Schema::Result::Person; {
        use base 'MyApp::Schema::Result';

        __PACKAGE__->table('person');
        __PACKAGE__->add_columns(
                person_id => {
                        data_type => 'varchar', 
                        size => '36', 
                        is_nullable => 0, 
                },
                fk_gender_id => {
                        data_type => 'varchar', 
                        size => '36', 
                        is_nullable => 0, 
                },
                name => {
                        data_type => 'varchar',
                        size => '24',
                        is_nullable => 0,
                },
        );

        __PACKAGE__->set_primary_key('person_id');
        __PACKAGE__->uuid_columns('person_id');

        __PACKAGE__->belongs_to(
                gender => 'MyApp::Schema::Gender',
                {'foreign.fk_gender_id' => 'self.fk_gender_id'}
        );
}


my $person = $schema->resultset('Person')->create({
                name='Joe Somebody',
                gender=>{label=>'male'},
        });
        
my $female = $schema->resultset('Gender')->find_female;
my $person = $schema->resultset('Person')->create({
                name='Mary Somebody',
                gender=>$female,
        });


      

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[email protected]

Reply via email to