DBIx::Class::Wrapper - A Moose role to allow your business model to wrap business code around a dbic model.



This package allows you to easily extend your DBIC Schema by Optionally wrapping its resultsets and result objects in your own business classes.

Basic usage with no specific wrapping at all

 package My::Model;
 use Moose;
 with qw/DBIx::Class::Wrapper/;


 my $schema = instance of DBIx schema
 my $app = My::Model->new( { dbic_schema => $schema } );
 ## And use the dbic resultsets-ish methods.
 my $products = $app->dbic_factory('Product'); ## Get a new instance of the Product resultset.

 ## Use classic DBIC methods as usual.
 my $p = $products->find(2);
 my $blue_ps = $products->search({ colour => blue });

Implement your own product class with business methods.

First you need a DBIC factory that will wrap the raw dbic object into your own class of product

 package My::Model::Wrapper::Factory::Product;
 use Moose; extends  qw/DBIx::Class::Wrapper::Factory/ ;
 sub wrap{
   my ($self , $o) = @_;
   return My::Model::O::Product->new({o => $o , factory => $self });

Then your Product business object class

 package My::Model::O::Product;
 use Moose;
 has 'o' => ( isa => 'My::Schema::Product', ## The raw DBIC object class.
              is => 'ro' , required => 1,
              handles => [ 'id' , 'name', 'active' ] ## handles standard properties
 ## A business method
 sub activate{
    my ($self) = @_;
    $self->o->update({ active => 1 });

Then from your main code, continue using the Product resultset as normal.

 my $product = $app->dbic_factory('Product')->find(1);
 ## But you can do
 ## so now
 $product->active() == 1;

Your own specialised resultset

Let's say you decide that from now, the bulk of your application should access only active products, leaving unlimited access to all product to a limited set of places.

 package My::Model::Wrapper::Factory::Product;
 use Moose;
 extends qw/DBIx::Class::Wrapper::Factory/;
 sub build_dbic_rs{
     my ($self) = @_;
     ## Note that you can always access your original business model
     ## from a factory (method bm).
     return $self->bm->dbic_schema->resultset('Product')->search_rs({ active => 1});
     ## This is a simple example. You can restrict your products set
     ## according to any current property of your business model for instance.
 sub wrap{ .. same .. }

Everywhere your application uses $app->dbic_factory('Product') is now restricted to active products only.

Surely you want admin parts of your application to access all products. So here's a very basic AllProducts:

 package My::Model::Wrapper::Factory::AllProduct;
 use Moose; extends qw/My::Model::Wrapper::Factory::Product/;
 sub build_dbic_rs{
   my ($self) = @_;
   ## Some extra security.
   unless( $self->bm->current_user()->is_admin() ){ confess "Sorry you cant access that"; }

   return $self->bm()->dbic_schema->resultset('Product')->search_rs();

Changing the factory base class.

Until now, all your custom factories were named My::Model::Wrapper::Factory::<something>.

If you want to customise the base class of those custom factories, you can do so by overriding the method _build_dbic_factory_baseclass in your model:

 package My::Model;

 use Moose;
 with qw/DBIx::Class::Wrapper/;

 sub _build_dbic_factory_baseclass{
    return 'My::Model::DBICFactory'; # for instance.

Then implement your factories as subpackages of My::Model::DBICFactory



Returns a new instance of DBIx::Class::Wrapper::Factory that wraps around the given DBIC ResultSet name if such a resultset exists. Dies otherwise.

Additionaly, you can set a ad-hoc resulset if you want to locally restrict your original resultset.


    my $f = $this->dbic_factory('Article');

    my $f = $this->dbic_factory('Article' , { dbic_rs => $schema->resultset('Article')->search_rs({ is_active => 1 }) });