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

3

6

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.

Benefit answered 18/2, 2010 at 19:47 Comment(1)
Why are you mapping the results to Moose classes? Why not use the DBIx::Class classes directly?Prompt
G
6

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.

Gemagemara answered 19/2, 2010 at 0:11 Comment(0)
W
3

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;
Wolframite answered 18/2, 2010 at 20:46 Comment(2)
How would you declare the Moose attributes if the schema is already defined by the DB (that is, DBIx::Class reads in the schema, rather than it being defined by the method calls you do above)?Rolfe
You mean runtime schema loading? Not gonna play nice. :)Smoothspoken
R
1

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.

Rolfe answered 18/2, 2010 at 20:46 Comment(2)
The next major version is being rewritten in Moose anyway, so I hear. that's been going around for years.Stringed
Matt had an inventive talk about it at Perl Oasis last month.Gemagemara

© 2022 - 2024 — McMap. All rights reserved.