File Coverage

blib/lib/Ark/Models.pm
Criterion Covered Total %
statement 55 87 63.2
branch 13 40 32.5
condition 3 12 25.0
subroutine 12 13 92.3
pod 2 5 40.0
total 85 157 54.1


line stmt bran cond sub pod time code
1             package Ark::Models;
2 5     5   346741 use Mouse;
  5         87967  
  5         26  
3              
4             extends 'Object::Container';
5              
6 5     5   3457 use Exporter::AutoClean;
  5         36830  
  5         240  
7 5     5   1286 use Path::Class 0.16 qw/file dir/;
  5         102218  
  5         825  
8              
9             has registered_namespaces => (
10             is => 'rw',
11             isa => 'HashRef',
12             default => sub { {} },
13             );
14              
15             has [qw/registered_classes objects/] => ( is => 'rw', default => sub { {} } );
16             has autoloader_rules => ( is => 'rw', default => sub { [] } );
17              
18 5     5   49 no Mouse;
  5         13  
  5         36  
19              
20             sub import {
21 14     14   2272 my $pkg = shift;
22 14   100     70 my $flag = shift || 'models';
23 14         32 my $caller = caller;
24              
25 14 100 50     78 if (($flag || '') =~ /^-base$/i) {
26 6         43 utf8->import;
27              
28             Exporter::AutoClean->export(
29             scalar caller,
30 1     1   214 register_namespaces => sub { $caller->register_namespaces(@_) },
31 6         50 );
32             }
33             else {
34 8 50       29 if ($pkg eq __PACKAGE__) {
35 0         0 die q[Don't use Ark::Model directly. You must create your own subclasses];
36             }
37              
38 8         36 $pkg->initialize;
39             }
40              
41 14         317 unshift @_, $pkg, $flag;
42             # goto $pkg->can('SUPER::import');
43 14         61 goto &Object::Container::import; # Some perl does not run avobe code, this is a quick fix for it.
44             }
45              
46             sub initialize {
47 9     9 0 16 my $pkg = shift;
48              
49             # build-in models: home, conf
50             $pkg->register(
51             home => sub {
52 1 50   1   15 return dir($ENV{ARK_HOME}) if $ENV{ARK_HOME};
53              
54 0         0 my $class = shift;
55              
56 0   0     0 $class = ref $class || $class;
57 0         0 (my $file = "${class}.pm") =~ s!::!/!g;
58              
59 0 0       0 if (my $path = $INC{$file}) {
60 0         0 $path =~ s/$file$//;
61              
62 0         0 $path = dir($path);
63              
64 0 0       0 if (-d $path) {
65 0         0 $path = $path->absolute;
66 0         0 while ($path->dir_list(-1) =~ /^b?lib$/) {
67 0         0 $path = $path->parent;
68             }
69              
70 0         0 return $path;
71             }
72             }
73              
74 0         0 die 'Cannot detect home directory, please set it manually: $ENV{ARK_HOME}';
75             },
76 9         74 );
77              
78             $pkg->register(
79             conf => sub {
80 1     1   22 my $home = shift->get('home');
81              
82 1         8 my $conf = {};
83 1         3 for my $fn (qw/config.pl config_local.pl/) {
84 2         98 my $file = $home->file($fn);
85 2 50       232 if (-e $file) {
86 0         0 my $c = do $file;
87 0 0       0 die "$file: $@" if $@;
88 0 0       0 die "$file: $!" unless defined $c;
89 0 0       0 die 'config should return HASHREF' unless ref($c) eq 'HASH';
90              
91 0         0 $conf = { %$conf, %$c };
92             }
93             }
94 1         54 $conf;
95             },
96 9         270 );
97              
98 9         207 $pkg->register_namespaces( '' => $pkg );
99             }
100              
101             sub adaptor {
102 0     0 0 0 my ($self, $info) = @_;
103              
104 0 0       0 my $class = $info->{class} or die q{Required class parameter};
105 0   0     0 my $constructor = $info->{constructor} || 'new';
106              
107 0         0 $self->ensure_class_loaded($class);
108              
109 0         0 my $instance;
110 0 0 0     0 if ($info->{deref} and my $args = $info->{args}) {
    0          
111 0 0       0 if (ref($args) eq 'HASH') {
    0          
112 0         0 $instance = $class->$constructor(%$args);
113             }
114             elsif (ref($args) eq 'ARRAY') {
115 0         0 $instance = $class->$constructor(@$args);
116             }
117             else {
118 0         0 die qq{Couldn't dereference: $args};
119             }
120             }
121             elsif ($info->{args}) {
122 0         0 $instance = $class->$constructor($info->{args});
123             }
124             else {
125 0         0 $instance = $class->$constructor;
126             }
127              
128 0         0 $instance;
129             }
130              
131             sub register_namespaces {
132 10     10 0 38 my ($self, %namespaces) = @_;
133 10 50       45 $self = $self->instance unless ref $self;
134              
135 10         73 while (my ($name, $ns) = each %namespaces) {
136 10         86 $self->registered_namespaces->{ $name } = $ns;
137             }
138             }
139              
140             sub get {
141 11     11 1 3995 my $self = shift;
142 11 100       62 $self = $self->instance unless ref $self;
143              
144 11         64 my $obj = eval { $self->SUPER::get(@_) };
  11         55  
145 11         1856 my $err = $@;
146              
147 11 100       44 return $obj if $obj;
148              
149 3         5 my $target = $_[0];
150 3 50       12 if ($target =~ /::/) {
151 3         6 my ($ns, @classes);
152 3         20 while ($target =~ s/::(.*?)$//) {
153 3         10 unshift @classes, $1;
154 3 50       19 $ns = $self->registered_namespaces->{$target} and last;
155             }
156 3 50       8 die $err unless $ns;
157              
158 3         8 my $class = $ns . '::' . join '::', @classes;
159              
160 3         17 $self->ensure_class_loaded($class);
161 3         2560 return $self->objects->{ $_[0] } = $class->new;
162             }
163             else {
164 0         0 die $err;
165             }
166             }
167              
168             sub ensure_class_loaded {
169 4     4 1 53 Mouse::load_class($_[1]);
170             }
171              
172             __PACKAGE__->meta->make_immutable;