DBIx-ActiveRecord

 view release on metacpan or  search on metacpan

lib/DBIx/ActiveRecord/Scope.pm  view on Meta::CPAN

package DBIx::ActiveRecord::Scope;
use strict;
use warnings;
use Carp;

use base qw/Exporter/;

our @ISA = qw/Exporter/;
my @delegates = qw/eq ne in not_in null not_null gt lt ge le like contains starts_with ends_with between where select limit offset lock group asc desc reorder reverse/;
our @EXPORT = (@delegates, qw/scoped_instance _scope _execute merge joins includes _includes _loads_includes update_all delete_all _is_relation/);

{
    no strict 'refs';
    foreach my $m (@delegates) {
        *{__PACKAGE__."::$m"} = sub {
            my $self = shift;
            my @args = @_;
            @args = map { $self->_is_relation($_) ? $_->{arel} : $_ } @args;
            $self->_scope($m, @args);
        };
    }
}

sub _is_relation {
    my ($self, $obj) = @_;
    return 0 if !ref $obj;
    return 0 if ref $obj eq 'HASH';
    return 0 if ref $obj eq 'ARRAY';
    return $obj->isa('DBIx::ActiveRecord::Relation');
}

sub _scope {
    my $self = shift;
    my $method = shift;
    my $s = $self->scoped;
    $s->{arel} = $s->{arel}->$method(@_);
    $s;
}

sub scoped_instance {
    my $self = shift;
    ref $self ? $self : $self->scoped;
}

sub update_all {
    my ($self, $sets) = @_;
    $self = $self->scoped;
    my $s = $self->{arel}->update($sets);
    my $sth = $self->{model}->dbh->prepare($s->to_sql);
    $sth->execute($s->binds) || croak $sth->errstr;
}

sub delete_all {
    my ($self) = @_;
    $self = $self->scoped;
    my $s = $self->{arel}->delete;
    my $sth = $self->{model}->dbh->prepare($s->to_sql);
    $sth->execute($s->binds) || croak $sth->errstr;
}

sub all {
    shift->_execute;
}

sub first {
    my $self = shift;
    my $s = $self->scoped_instance;
    my $org = $s->{arel}->clone;
    $s->{arel} = $s->{arel}->limit(1);
    my $r = $s->_execute;
    $s->{arel} = $org;
    @$r ? $r->[0] : undef;
}

sub last {
    my $self = shift;
    my $s = $self->scoped_instance;
    my $org = $s->{arel}->clone;
    $s->{arel} = $s->{arel}->limit(1)->reverse;
    my $r = $s->_execute;
    $s->{arel} = $org;
    @$r ? $r->[0] : undef;
}

sub _execute {
    my $self = shift;
    my $s = $self->scoped_instance;
    my $rs = $s->{model}->instantiates_by_relation($s);
    $s->_loads_includes($s->{_includes}, $rs);
    $rs;
}

sub _loads_includes {
    my ($self, $inc, $rs) = @_;
    foreach my $k (keys %$inc) {
        my $opt = $inc->{$k};
        my $model = $opt->{model};
        my $primary_key = $opt->{primary_key};
        my $foreign_key = $opt->{foreign_key};
        my %pkeys;
        my $search_key = $opt->{belongs_to} ? $primary_key : $foreign_key;
        my $my_key = $opt->{belongs_to} ? $foreign_key : $primary_key;
        my $s = $opt->{belongs_to} ? $model->unscoped : $model->scoped;
        my @keys = map {$_->$my_key} grep {$pkeys{$_->$my_key} = 1} @$rs;
        next if !keys %pkeys;



( run in 3.453 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )