File Coverage

blib/lib/Class/AlzaboWrapper.pm
Criterion Covered Total %
statement 27 101 26.7
branch 1 24 4.1
condition 0 6 0.0
subroutine 9 24 37.5
pod 11 11 100.0
total 48 166 28.9


line stmt bran cond sub pod time code
1             package Class::AlzaboWrapper;
2              
3 1     1   579769 use strict;
  1         2  
  1         37  
4              
5 1     1   6 use vars qw($VERSION);
  1         2  
  1         41  
6              
7             $VERSION = '0.14';
8              
9 1     1   567 use Class::AlzaboWrapper::Cursor;
  1         3  
  1         28  
10              
11 1     1   6 use Exception::Class ( qw( Class::AlzaboWrapper::Exception Class::AlzaboWrapper::Exception::Params ) );
  1         2  
  1         10  
12             Class::AlzaboWrapper::Exception->Trace(1);
13             Class::AlzaboWrapper::Exception::Params->Trace(1);
14              
15 1     1   474 use Params::Validate qw( validate validate_pos validate_with SCALAR UNDEF ARRAYREF HASHREF );
  1         2  
  1         173  
16             Params::Validate::validation_options
17             ( on_fail =>
18             sub { Class::AlzaboWrapper::Exception::Params->throw
19             ( message => join '', @_ ) } );
20              
21             my %TableToClass;
22             my %ClassToTable;
23             my %ClassAttributes;
24              
25             BEGIN
26             {
27 1     1   3 foreach my $meth ( qw( select update delete is_live ) )
28             {
29 4     0   11 my $sub = sub { shift->row_object->$meth(@_) };
  0         0  
30              
31 1     1   5 no strict 'refs';
  1         14  
  1         49  
32 4         6 *{ __PACKAGE__ . "::$meth" } = $sub;
  4         606  
33             }
34             }
35              
36             sub import
37             {
38 1     1   5 my $class = shift;
39              
40             # called via 'use base'
41 1 50       20 return unless @_;
42              
43 0           my %p =
44             validate_with( params => \@_,
45             spec =>
46             { caller => { type => SCALAR,
47             default => (caller(0))[0] },
48             base => { type => SCALAR,
49             default => __PACKAGE__ },
50             },
51             allow_extra => 1,
52             );
53              
54 0           my $base = delete $p{base};
55 0           eval "package $p{caller}; use base '$base'";
56              
57 0           $class->_make_methods(%p);
58             }
59              
60             sub _make_methods
61             {
62 0     0     my $class = shift;
63              
64 0           my %p = validate( @_,
65             { skip => { type => SCALAR | ARRAYREF, default => [] },
66             table => { isa => 'Alzabo::Table' },
67             caller => { type => SCALAR, default => $class },
68             }
69             );
70              
71 0           my $caller = delete $p{caller};
72              
73 0           $caller->SetAlzaboTable( delete $p{table} );
74 0           $caller->MakeColumnMethods(%p);
75             }
76              
77             sub SetAlzaboTable
78             {
79 0     0 1   my $class = shift;
80 0           my ($table) = validate_pos( @_, { isa => 'Alzabo::Table' } );
81              
82 0           $TableToClass{ $table->name } = $class;
83 0           $ClassToTable{$class} = $table;
84             }
85              
86             sub Table
87             {
88 0   0 0 1   my $class = ref $_[0] || $_[0];
89              
90 0 0         Class::AlzaboWrapper::Exception->throw
91             ( error => "Must call SetTable() before calling Table() on $class" )
92             unless $ClassToTable{$class};
93              
94 0           return $ClassToTable{$class};
95              
96             }
97             # deprecated
98             *table = \&Table;
99              
100             sub MakeColumnMethods
101             {
102 0     0 1   my $class = shift;
103 0           my %p = validate( @_,
104             { skip => { type => SCALAR | ARRAYREF, default => [] },
105             }
106             );
107              
108 0 0         my %skip = map { $_ => 1 } ref $p{skip} ? @{ $p{skip} } : $p{skip};
  0            
  0            
109              
110 0           my $table = $class->Table;
111 0           foreach my $name ( map { $_->name } $table->columns )
  0            
112             {
113 0 0         next if $skip{$name};
114              
115 0           $class->_RecordAttributeCreation( $class => $name );
116              
117 0           my $cache_key = '__cache__' . $name;
118              
119 0     0     my $sub = sub { my $self = shift;
120              
121 0 0         return $self->{$cache_key}
122             if exists $self->{$cache_key};
123              
124 0           $self->{$cache_key} = $self->row_object->select($name);
125 0           };
126              
127 1     1   5 no strict 'refs';
  1         1  
  1         645  
128 0           *{"$class\::$name"} = $sub;
  0            
129             }
130             }
131              
132 0     0     sub _RecordAttributeCreation { push @{ $ClassAttributes{ $_[1] } }, $_[2] }
  0            
133             # deprecated
134             *_record_attribute_creation = \&_RecordAttributeCreation;
135              
136             sub new
137             {
138 0     0 1   my $class = shift;
139              
140 0           my @pk = $class->table->primary_key;
141              
142 0           my @pk_spec =
143 0           map { $_->name => { type => SCALAR | UNDEF, optional => 1 } } @pk;
144              
145 0           my %p =
146             validate_with( params => \@_,
147             spec =>
148             { object =>
149             { isa => 'Alzabo::Runtime::Row', optional => 1 },
150             @pk_spec,
151             },
152             allow_extra => 1,
153             );
154              
155 0           my %pk;
156 0           foreach my $col (@pk)
157             {
158 0 0         if ( exists $p{ $col->name } )
159             {
160 0           $pk{ $col->name } = $p{ $col->name };
161             }
162             }
163              
164 0           my $row;
165 0 0         if ( keys %pk == @pk )
    0          
166             {
167 0           $row = eval { $class->table->row_by_pk( pk => \%pk ) };
  0            
168             }
169             elsif ( exists $p{object} )
170             {
171 0           $row = $p{object};
172             }
173             else
174             {
175 0 0         $row = $class->_new_row(%p) if $class->can('_new_row');
176             }
177              
178 0 0         return unless $row;
179              
180 0           my $self = bless { row => $row }, $class;
181              
182 0 0         $self->_init(%p) if $self->can('_init');
183              
184 0           return $self;
185             }
186              
187             sub create
188             {
189 0     0 1   my $class = shift;
190 0           my %p = @_;
191              
192 0           my %values;
193              
194 0           for my $c ( map { $_->name } $class->table->columns )
  0            
195             {
196 0 0         $values{$c} = delete $p{$c} if exists $p{$c};
197             }
198              
199 0           my $row =
200             $class->table->insert
201             ( values => \%values );
202              
203 0           return $class->new( object => $row, %p );
204             }
205              
206             sub potential
207             {
208 0     0 1   my $class = shift;
209              
210             return
211 0           $class->new( object => $class->table->potential_row( values => {@_} ) );
212             }
213              
214 0     0 1   sub Columns { shift->table->columns(@_) }
215             *Column = \&Columns;
216             # deprecated
217             *columns = \&Columns;
218             *column = \&Columns;
219              
220             sub NewCursor
221             {
222 0     0 1   my $self = shift;
223 0           my $cursor = shift;
224              
225             return
226 0           Class::AlzaboWrapper::Cursor->new
227             ( cursor => $cursor );
228             }
229             # deprecated
230             *cursor = \&NewCursor;
231              
232              
233 0     0 1   sub TableToClass { $TableToClass{ $_[1]->name } }
234             # deprecated
235             *table_to_class = \&TableToClass;
236              
237             sub AlzaboAttributes
238             {
239 0   0 0 1   my $class = ref $_[0] || $_[0];
240              
241 0           @{ $ClassAttributes{$class} };
  0            
242             }
243             # deprecated
244             *alzabo_attributes = \&AlzaboAttributes;
245              
246 0     0 1   sub row_object { $_[0]->{row} }
247              
248              
249             1;
250              
251             __END__