DBIx-Class-Wrapper

 view release on metacpan or  search on metacpan

lib/DBIx/Class/Wrapper.pm  view on Meta::CPAN


=head2 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 .. }
 1;

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();
 }


=head2 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

=cut

has 'dbic_schema' => ( is => 'rw' , isa => 'DBIx::Class::Schema' , required => 1 );
has 'dbic_factory_baseclass' => ( is => 'ro' , isa => 'Str' , lazy_build => 1);

has '_dbic_dbic_fact_classes' => ( is => 'ro' , isa => 'HashRef[Bool]' , lazy_build => 1); 

sub _build_dbic_factory_baseclass{
    my ($self) = @_;
    return ref ($self).'::Wrapper::Factory';
}

sub _build__dbic_dbic_fact_classes{
    my ($self) = @_;
    my $baseclass = $self->dbic_factory_baseclass();
    my $res = {};
    my $mp = Module::Pluggable::Object->new( search_path => [ $baseclass ]);
    foreach my $candidate_class ( $mp->plugins() ){
	Class::Load::load_class( $candidate_class );
	# Code is loaded
	unless( $candidate_class->isa('DBIx::Class::Wrapper::Factory') ){
	    warn "Class $candidate_class does not extend DBIx::Class::Wrapper::Factory.";
	    next;
	}
	# And inherit from the right class.
	$res->{$candidate_class} = 1;
    }
    return $res;
}

=head1 METHODS

=head2 dbic_factory

Returns a new instance of L<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.

usage:

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

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

=cut

sub dbic_factory{
  my ($self , $name , $init_args ) = @_;
  unless( defined $init_args ){
      $init_args = {};
  }
  unless( $name ){
    confess("Missing name in call to dbic_factory");
  }
  my $class_name = $self->dbic_factory_baseclass().'::'.$name;

  ## Build a class dynamically if necessary
  unless( $self->_dbic_dbic_fact_classes->{$class_name} ){
    ## We need to build such a class.
    Moose::Meta::Class->create($class_name => ( superclasses => [ 'DBIx::Class::Wrapper::Factory' ] ));
    $self->_dbic_dbic_fact_classes->{$class_name} = 1;
  }
  ## Ok, $class_name is now there

  ## Note that the factory will built its own resultset from this model and the name



( run in 1.570 second using v1.01-cache-2.11-cpan-39bf76dae61 )