CatalystX-CRUD-ModelAdapter-DBIC

 view release on metacpan or  search on metacpan

lib/CatalystX/CRUD/ModelAdapter/DBIC.pm  view on Meta::CPAN

package CatalystX::CRUD::ModelAdapter::DBIC;
use warnings;
use strict;
use base qw(
    CatalystX::CRUD::ModelAdapter
    CatalystX::CRUD::Model::Utils
);
use MRO::Compat;
use mro 'c3';
use Scalar::Util qw( weaken );
use Carp;
use Data::Dump qw( dump );
use Sort::SQL;

__PACKAGE__->mk_ro_accessors(qw( treat_like_int ));

our $VERSION = '0.15';

=head1 NAME

CatalystX::CRUD::ModelAdapter::DBIC - CRUD for Catalyst::Model::DBIC::Schema

=head1 SYNOPSIS

 # create an adapter class (NOTE not in ::Model namespace)
 package MyApp::MyDBICAdapter;
 use strict;
 use base qw( CatalystX::CRUD::ModelAdapter::DBIC );
 
 1;
 
 # your main DBIC::Schema model
 package MyApp::Model::MyDBIC;
 use strict;
 use base qw( Catalyst::Model::DBIC::Schema );
 
 1;
 
=head1 DESCRIPTION

CatalystX::CRUD::ModelAdapter::DBIC implements the CatalystX::CRUD::ModelAdapter
API for DBIx::Class.

=head1 METHODS

=head2 new( I<opts> )

Overrides base method to initialize treats_like_int, ne_sign and 
use_ilike values.

=cut

# TODO others?
my %is_iliker = (
    Pg         => 1,
    PostgreSQL => 1,
);

sub new {
    my $self = shift->next::method(@_);

    # what kind of db driver are we using.
    # makes a difference in make_sql_query().
    my $db_type
        = $self->app_class->model( $self->model_name )->storage->sqlt_type;

    #warn "DBIC driver: " . $db_type;

    $self->use_ilike( exists $is_iliker{$db_type} );

lib/CatalystX/CRUD/ModelAdapter/DBIC.pm  view on Meta::CPAN

        %opts = %{ $controller->model_meta->{resultset_opts} };
    }

    # ORDER BY
    #dump $field_names;
    if ( exists $query->{sort_by} ) {
        $opts{order_by} ||= $query->{sort_by};

        # default is to sort by PK, which might not be prefixed.
        my $ss = Sort::SQL->parse( $opts{order_by} );

        #dump $ss;
        my @order_by;
        for my $clause (@$ss) {
            if ( $clause->[0] !~ m/\./ ) {

                if ( $c->req->params->{'cxc-m2m'} ) {

                    # TODO m2m

                }
                else {

                    # o2m
                    my $name = "me." . $clause->[0];
                    if ( grep { $_ eq $name } @$field_names ) {
                        $clause->[0] = $name;
                    }
                }
            }
            push @order_by, { '-' . lc( $clause->[1] ) => $clause->[0] };
        }
        $opts{order_by} = \@order_by;
    }

    #dump \%opts;
    $query->{OPTS} = \%opts;

    $c->log->debug( "query: " . dump $query ) if $c->debug;

    return $query;
}

=head2 make_sql_query( I<controller>, I<context>, I<field_names> )

Override method in CatalystX::CRUD::Model::Utils to mimic
ACCEPT_CONTEXT by setting I<context> in $self. 

Otherwise, acts just like CatalystX::CRUD::Model::Utils->make_sql_query().

=cut

sub make_sql_query {
    my $self        = shift;
    my $controller  = shift;
    my $c           = shift;
    my $field_names = shift;

    # Model::Utils (make_sql_query) assumes ACCEPT_CONTEXT accessor
    $self->{context} = $c;
    weaken( $self->{context} );

    my $q = $self->next::method($field_names);

    #carp "make_sql_query : " . dump $q;

    if ( $q->{query_obj} ) {
        $q->{query} = $q->{query_obj}->dbic;
    }

    #carp "make_sql_query : " . dump $q;

    return $q;
}

=head2 search_related( I<controller>, I<context>, I<obj>, I<relationship> [, I<query> ] )

Implements required method. Returns array ref of
objects related to I<obj> via I<relationship>. I<relationship>
should be a method name callable on I<obj>.

=head2 iterator_related( I<controller>, I<context>, I<obj>, I<relationship> [, I<query> ] )

Like search_related() but returns an iterator.

=head2 count_related( I<controller>, I<context>, I<obj>, I<relationship> [, I<query> ] )

Like search_related() but returns an integer.

=cut

sub search_related {
    my ( $self, $controller, $c, $obj, $rel, $query ) = @_;
    $query ||= $self->make_query( $controller, $c );
    return [ $obj->$rel->search( $query->{WHERE}, $query->{OPTS} ) ];
}

sub iterator_related {
    my ( $self, $controller, $c, $obj, $rel, $query ) = @_;
    $query ||= $self->make_query( $controller, $c );
    return scalar $obj->$rel->search( $query->{WHERE}, $query->{OPTS} );
}

sub count_related {
    my ( $self, $controller, $c, $obj, $rel, $query ) = @_;
    $query ||= $self->make_query( $controller, $c );
    return $obj->$rel->count( $query->{WHERE}, $query->{OPTS} );
}

=head2 add_related( I<controller>, I<context>, I<obj>, I<rel_name>, I<foreign_value> )

Implements optional method as defined by core API. I<rel_name>
should be a method name callable by I<obj>.

=cut

sub add_related {
    my ( $self, $controller, $c, $obj, $rel, $for_val ) = @_;
    my $rinfo = $self->_get_rel_meta( $controller, $c, $obj, $rel );

    #carp "add_related: " . dump $rinfo;



( run in 2.202 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )