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 )