File Coverage

lib/DBIx/ActiveRecord.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package DBIx::ActiveRecord;
2              
3 1     1   50750 use 5.008008;
  1         4  
  1         43  
4 1     1   6 use strict;
  1         2  
  1         35  
5 1     1   5 use warnings;
  1         2  
  1         29  
6              
7 1     1   434 use DBI;
  0            
  0            
8              
9             our $VERSION = '0.03';
10              
11             our $DBH;
12             our $SINGLETON;
13             our %GLOBAL;
14              
15             sub connect {
16             my ($self, $data_source, $user_name, $auth, $attr) = @_;
17             $DBH = DBI->connect($data_source, $user_name, $auth, $attr);
18             $SINGLETON = bless {dbh => $DBH}, $self;
19             $self->init;
20             }
21              
22             sub init {
23             my $self = shift;
24             foreach my $package (keys %GLOBAL) {
25             $self->_load_model($package);
26             $self->_make_field_accessors($package);
27             }
28             $self->_define_associates;
29             }
30              
31             sub _load_model {
32             my ($self, $package) = @_;
33             my $file = $package;
34             $file =~ s/::/\//;
35             $file .= ".pm";
36             eval {require $file};
37             }
38              
39             sub _make_field_accessors {
40             my $self = shift;
41             my $pkg = shift;
42             no strict 'refs';
43             foreach my $col (@{$pkg->_global->{columns}}) {
44             *{$pkg."::$col"} = sub {
45             my $self = shift;
46             @_ ? $self->set_column($col, @_) : $self->get_column($col);
47             };
48             }
49             }
50              
51             sub _define_associates {
52             my $self = shift;
53             foreach my $package (keys %GLOBAL) {
54             $self->_define_belong_to($package, @$_) for @{$package->_global->{belongs_to}||[]};
55             $self->_define_has_relation($package, @$_) for @{$package->_global->{has_relation}||[]};
56             }
57             }
58              
59             sub _define_belong_to {
60             my ($self, $pkg, $name, $package, $opt) = @_;
61              
62             $opt->{primary_key} = 'id' if !$opt->{primary_key};
63             if (!$opt->{foreign_key}) {
64             $package =~ /([^:]+)$/;
65             $opt->{foreign_key} = lc($1)."_id";
66             }
67              
68             $pkg->_global->{joins}->{$name} = {%$opt, model => $package, belongs_to => 1, one => 1};
69              
70             no strict 'refs';
71             *{$pkg."::$name"} = sub {
72             my $self = shift;
73              
74             return $self->{associates_cache}->{$name} if exists $self->{associates_cache}->{$name};
75              
76             my $m = $opt->{foreign_key};
77             $package->unscoped->eq($opt->{primary_key} => $self->$m)->first;
78             };
79             }
80              
81             sub _define_has_relation {
82             my ($self, $pkg, $name, $package, $opt, $has_one) = @_;
83              
84             $opt->{primary_key} = 'id' if !$opt->{primary_key};
85             if (!$opt->{foreign_key}) {
86             $pkg =~ /([^:]+)$/;
87             $opt->{foreign_key} = lc($1)."_id";
88             }
89              
90             $pkg->_global->{joins}->{$name} = {%$opt, model => $package, one => $has_one};
91              
92             no strict 'refs';
93             *{$pkg."::$name"} = sub {
94             my $self = shift;
95              
96             return $self->{associates_cache}->{$name} if exists $self->{associates_cache}->{$name};
97              
98             my $m = $opt->{primary_key};
99             my $s = $package->eq($opt->{foreign_key}, $self->$m);
100             $has_one ? $s->limit(1)->first : $s;
101             };
102             }
103              
104             sub dbh {$DBH}
105              
106             sub transaction {
107             my ($self, $coderef) = @_;
108             $self->dbh->begin_work;
109             eval {$coderef->()};
110             if ($@) {
111             $self->dbh->rollback;
112             } else {
113             $self->dbh->commit;
114             }
115             }
116              
117             sub DESTROY {
118             my ($self) = @_;
119             $SINGLETON = undef;
120             $self->dbh->disconnect if $self->dbh;
121             }
122              
123             1;
124             __END__