Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an easy way to map DBIx::Class results to my custom Moose classes?

It seems kind of a pain to have my Moose classes. Then to use DBIx::Class to get a result set..then to manually map my result set to the moose classes.

like image 414
mike park Avatar asked Feb 18 '10 19:02

mike park


3 Answers

If you're having to map back and forth between Moose classes and a DBIC schema, you may want to look at a persistent object store like KiokuDB instead.

You lose some of the features of a Relational Database, especially if you have an existing schema but you gain a lot of features the main one being quiet mapping between the data-store and your Object model. The DBI back-end for KiokuDB is probably the best example of this trade off. The database is highly de-normalized, but that's because it's working as effectively a key-store.

KiokuDB however can work with storage engines that are optimized for this kind of data. It supports several of the current crop of "NoSQL" celebrities including CouchDB, and MongoDB. It also supports the older fan favorite BerkelyDB.

Kioku isn't the answer for every problem, but it is used quite successfully for Parking Mobility to handle all the data storage seamlessly.

like image 140
perigrin Avatar answered Nov 15 '22 12:11

perigrin


You can use Moose with DBIC no problem. Actually I enjoy using MooseX::Declare since I find the extended syntax is very useful when designing solid public apis, for example:

use MooseX::Declare;
class MyApp::Schema::Result::Geo::Division
 extends MyApp::Schema::Result {
    use Locale::Geocode::Division;
 __PACKAGE__->table('division');
 __PACKAGE__->add_columns(
  fk_territory_id => {
   data_type => 'char',
   size => '36',
  },
  division_id => {
   data_type => 'char',
   size => '36',
  },
  code => {
            data_type => 'varchar',
   size => '5',
  },
     created => {
   data_type => 'datetime',
   set_on_create => 1,
  },
 );

 __PACKAGE__->set_primary_key('fk_territory_id','division_id');
 __PACKAGE__->uuid_columns('division_id');
    __PACKAGE__->add_unique_constraint(['fk_territory_id','code']);

 __PACKAGE__->belongs_to(
  territory => 'MyApp::Schema::Result::Geo::Territory',
  {'foreign.territory_id' => 'self.fk_territory_id'},
 );
    method as_geocode_division {
        Locale::Geocode::Division->new($self->code);
    }     
 __PACKAGE__->meta->make_immutable(inline_constructor => 0);
} 1;
like image 30
user276468 Avatar answered Nov 15 '22 13:11

user276468


It sounds like you're describing exactly what I wrote recently in order to map Moose attribute values onto Rose::DB::Object values (with the db object and objectmanager contained in private attributes) and vice versa. I originally used triggers around each Moose attribute to write to the Rose object immediately, but later abandoned that approach and lazily-wrote the values only when needed (i.e. at the time of a ->save() operation). I implemented it using a few roles and a sugar class which automatically installed an attribute trait indicating "I am a table field" for the relevant attributes.

But don't do what I did -- just use DBIx::Class directly! The next major version is being rewritten in Moose anyway, so I hear.

like image 40
Ether Avatar answered Nov 15 '22 12:11

Ether