File Coverage

blib/lib/Class/Dot/Model.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             # $Id: Model.pm 4 2007-09-13 10:16:35Z asksol $
2             # $Source$
3             # $Author: asksol $
4             # $HeadURL: https://class-dot-model.googlecode.com/svn/trunk/lib/Class/Dot/Model.pm $
5             # $Revision: 4 $
6             # $Date: 2007-09-13 12:16:35 +0200 (Thu, 13 Sep 2007) $
7             package Class::Dot::Model;
8              
9 1     1   26783 use strict;
  1         2  
  1         38  
10 1     1   4 use warnings;
  1         3  
  1         27  
11 1     1   934 use version; our $VERSION = qv('0.1.3');
  1         2824  
  1         6  
12 1     1   98 use 5.006_001;
  1         7  
  1         42  
13              
14 1     1   7 use Carp qw(croak);
  1         2  
  1         87  
15 1     1   1029 use Params::Util qw(_ARRAY);
  1         13091  
  1         131  
16 1     1   1046 use Config::PlConfig;
  0            
  0            
17             use Class::Dot::Model::Util qw(
18             push_base_class
19             install_coderef run_as_call_class
20             );
21              
22             my $BASE_CLASS = 'DBIx::Class::Schema';
23              
24             my @INIT_METHODS = qw(
25             load_classes
26             );
27              
28             my %DSN_PARAMS = (
29             hostname => q{%s},
30             database => q{%s},
31             port => q{%d},
32             );
33              
34             my %DSN_DRIVER_REWRITE = (
35             mysql => {
36             hostname => 'host',
37             },
38             Pg => {
39             hostname => 'hostname',
40             database => 'dbname',
41             },
42             SQLite => {
43             database => 'dbname',
44             },
45             );
46              
47             my $dsn_param_rewrite = sub {
48             $DSN_DRIVER_REWRITE{$_[0]} ? $DSN_DRIVER_REWRITE{$_[0]} : $_[0];
49             };
50              
51             sub requires {
52             return $BASE_CLASS;
53             }
54              
55             my @MODULES_THAT_IMPORTS_US;
56              
57             sub import {
58             my $class = shift;
59             my $call_class = caller 0;
60             my %argv;
61            
62             if (scalar @_ > 1) {
63             %argv = @_;
64             }
65              
66             push_base_class( $BASE_CLASS => $call_class );
67              
68             for my $init_method (@INIT_METHODS) {
69             run_as_call_class( $call_class, $init_method );
70             }
71              
72             return if not defined $argv{domain};
73             return if $call_class->can('new');
74              
75             my $dbconfig = _load_dbconfig( $argv{domain}, $argv{host} );
76             my $dsnstring = _create_dsn_with_config($dbconfig);
77              
78             _install_constructor($call_class, $dsnstring, $dbconfig);
79              
80             push @MODULES_THAT_IMPORTS_US, $call_class;
81              
82             return;
83             }
84              
85             # Install a sighandler that walks through all modules that imports
86             # us + inherits from DBIx::Class and then disconnects them.
87             BEGIN {
88             $SIG{INT} = sub {
89             for my $module (@MODULES_THAT_IMPORTS_US) {
90             if ($module->isa($BASE_CLASS)) {
91             $module->storage->disconnect();
92             }
93             }
94             }
95             }
96              
97             sub _load_dbconfig {
98             my ($domain, $host) = @_;
99              
100             my $plconfig = Config::PlConfig->new({
101             host => $host,
102             domain => $domain,
103             });
104             my $config = $plconfig->load()->{database};
105              
106             return $config;
107             }
108              
109             sub _install_constructor {
110             my ($call_class, $dsn, $config) = @_;
111              
112             my $new_coderef = sub {
113             my ($class, $options_ref) = @_;
114             $options_ref ||= { };
115              
116             my $self = $class->connect($dsn, $config->{username}, $config->{password});
117              
118             NOSTRICT: {
119             no strict 'refs'; ## no critic
120             if (my $build_ref = *{ $class . '::BUILD' }{CODE}) { ## no critic
121             $build_ref->($self, $options_ref);
122             }
123             };
124              
125             return $self;
126             };
127            
128             return install_coderef($new_coderef => $call_class, 'new');
129             }
130              
131             sub _create_dsn_with_config {
132             my ($config) = @_;
133              
134             # Format the DSN string.
135             # %DSN_PARAMS holds the values we support, and values submitted
136             # are copied to %dsn_params;
137             my %dsn_params;
138             my $dsn_format = qq{
139             DBI:$config->{driver}:
140             };
141              
142             DSNPARAM:
143             for my $param_name (sort keys %DSN_PARAMS) {
144             my $param_type = $DSN_PARAMS{$param_name};
145             next DSNPARAM if not defined $config->{$param_name};
146             $dsn_params{$param_name} = $config->{$param_name};
147              
148             $dsn_format .= join q{=}, (
149             $dsn_param_rewrite->($param_name),
150             $param_type
151             );
152             $dsn_format .= q{;};
153              
154             };
155             chop $dsn_format;
156             $dsn_format =~ s/\s*//xmsg;
157              
158             no warnings 'uninitialized'; ## no critic;
159             my $dsn = sprintf $dsn_format,
160             map { $dsn_params{$_} } sort keys %dsn_params;
161              
162             return $dsn;
163             }
164              
165             1;
166              
167             __END__