File Coverage

blib/lib/DBIx/QuickORM/Row/Async.pm
Criterion Covered Total %
statement 63 95 66.3
branch 17 64 26.5
condition 2 4 50.0
subroutine 13 20 65.0
pod 0 12 0.0
total 95 195 48.7


line stmt bran cond sub pod time code
1             package DBIx::QuickORM::Row::Async;
2 24     24   182 use strict;
  24         62  
  24         1055  
3 24     24   145 use warnings;
  24         47  
  24         1954  
4              
5             our $VERSION = '0.000019';
6              
7 24     24   167 use Carp();
  24         68  
  24         511  
8 24     24   128 use Scalar::Util();
  24         93  
  24         6031  
9              
10             use overload (
11 0 0   0   0 'bool' => sub { $_[0]->{invalid} ? 0 : 1 },
12 24     24   197 );
  24         62  
  24         350  
13              
14             sub isa {
15 0     0 0 0 my ($this, $check) = @_;
16              
17 0 0       0 return 1 if $check eq __PACKAGE__;
18 0 0       0 return 1 if $check eq 'DBIx::QuickORM::Row';
19 0 0       0 return 1 if DBIx::QuickORM::Row->isa($check);
20              
21 0 0       0 if (my $class = Scalar::Util::blessed($this)) {
22              
23 0 0       0 if ($this->ready) {
24 0         0 my $a = $_[0];
25 0         0 $_[0] = $this->swapout;
26 0 0       0 return $_[0]->isa($check) unless Scalar::Util::refaddr($a) eq Scalar::Util::refaddr($_[0]);
27             }
28              
29 0 0       0 return 1 if $check eq $class;
30 0 0       0 return 1 if $check eq $this->{row_class};
31 0 0       0 return 1 if $this->{row_class}->isa($check);
32             }
33              
34 0         0 return 0;
35             }
36              
37             sub can {
38 4     4 0 228 my ($this, $check) = @_;
39              
40 4 50       76 if (my $class = Scalar::Util::blessed($this)) {
41 4 50       23 if ($this->ready) {
42 4         28 $_[0] = $this->swapout;
43 4         5614 return $_[0]->isa($check);
44             }
45              
46 0 0       0 return $this->{row_class}->can($check) if $this->{row_class};
47             }
48              
49 0         0 $this->SUPER::can($check);
50             }
51              
52             sub DOES {
53 0     0 0 0 my ($this) = @_;
54              
55 0 0       0 my $class = Scalar::Util::blessed($this) or return undef;
56              
57 0 0       0 if ($this->ready) {
58 0         0 $_[0] = $this->swapout;
59 0         0 return $_[0]->DOES(@_);
60             }
61              
62 0 0       0 return $this->{row_class}->DOES(@_) if $this->{row_class};
63 0         0 return undef;
64             }
65              
66             sub new {
67 4     4 0 35 my $class = shift;
68 4         296 my $self = bless({@_}, $class);
69              
70 4 50       212 Carp::croak("You must specify an 'async'") unless $self->{async};
71              
72             Carp::croak("'$self->{async}' does not implement the 'DBIx::QuickORM::Role::Async' role")
73 4 50       48 unless $self->{async}->DOES('DBIx::QuickORM::Role::Async');
74              
75 4   50     264 $self->{state_method} //= 'state_select_row';
76 4   50     59 $self->{state_args} //= [];
77              
78 4         4669 return $self;
79             }
80              
81 1     1 0 56 sub async { $_[0]->{async} }
82 0     0 0 0 sub auto_refresh { $_[0]->{auto_refresh} }
83              
84 0 0   0 0 0 sub is_invalid { $_[0]->swapout(@_)->{invalid} ? 1 : 0 }
85 0 0   0 0 0 sub is_valid { $_[0]->swapout(@_)->{invalid} ? 0 : 1 }
86              
87             sub ready {
88 10     10 0 208838 my ($self) = @_;
89              
90 10 50       101 return 1 if $self->{invalid};
91              
92 10 100       175 return undef unless $self->{async}->ready();
93              
94 7         42 return $self->row;
95             }
96              
97             sub row {
98 14     14 0 38 my $self = shift;
99              
100 14 100       79 return $self->{row} if exists $self->{row};
101 5 50       20 return $self->{row} = undef if $self->{invalid};
102              
103 5         14 my $async = $self->{async};
104 5         46 my $data = $async->next();
105              
106 4 50       19 if ($data) {
107 4         20 $async->set_done();
108             }
109             else {
110 0         0 $self->{invalid} = 1;
111 0         0 return $self->{row} = undef;
112             }
113              
114 4         41 my %args = %$self;
115 4         14 delete $args{async};
116 4         9 my $auto_refresh = delete $args{auto_refresh};
117              
118 4         14 my $meth = $self->{state_method};
119 4         30 my $row = $self->{row} = $async->connection->$meth(@{$self->{state_args}}, source => $async->source, fetched => $data);
  4         65  
120              
121 4 50       13 $row->refresh if $auto_refresh;
122              
123 4         35 return $row;
124             }
125              
126             sub swapout {
127 6     6 0 26 my ($self) = @_;
128              
129 6 50       22 return $self if $self->{invalid};
130 6 50       34 my $row = $self->row or return $self;
131 6         20 return $_[0] = $row;
132             }
133              
134             sub cancel {
135 0     0 0 0 my $self = shift;
136              
137 0 0       0 return if $self->{invalid};
138              
139 0         0 $self->{async}->cancel();
140              
141 0         0 $self->{invalid} = 1;
142             }
143              
144             sub AUTOLOAD {
145 2     2   202 my ($self) = @_;
146              
147 2         19 our $AUTOLOAD;
148 2         6 my $meth = $AUTOLOAD;
149 2         66 $meth =~ s/^.*:://;
150              
151 2         11 $_[0] = $self->swapout;
152              
153             Carp::croak("This async row is not valid, the query probably returned no data, or the query was canceled")
154 2 50       26 if $self->{invalid};
155              
156 2 50       30 my $sub = $_[0]->can($meth) or Carp::croak(qq{Can't locate object method "$meth" via package "} . ref($_[0]) . '"');
157              
158 2         31 goto &$sub;
159             }
160              
161             sub DESTROY {
162 4     4   10 my $self = shift;
163 4 50       14 return if $self->{invalid};
164 4         62 delete $self->{async};
165 4         314 $self->{invalid} = 1;
166             }
167              
168             1;