File Coverage

blib/lib/DBIx/Factory.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package DBIx::Factory;
2              
3 1     1   25677 use Moose;
  0            
  0            
4             use namespace::autoclean;
5             use Scalar::Util qw/ blessed /;
6             use Config::Any;
7             use File::Spec;
8             use DBI;
9              
10             our $VERSION = "0.09";
11              
12             has "config_base" => (
13             is => "ro",
14             isa => "Str",
15             required => 1,
16             default => sub { defined $ENV{DBIF_BASE} ? $ENV{DBIF_BASE} : q{} },
17             );
18              
19             has "config_file" => (
20             is => "rw",
21             isa => "Str",
22             required => 1,
23             default => q{},
24             );
25              
26             around BUILDARGS => sub {
27             my ($next_method, $class, @args) = @_;
28              
29             $class->$next_method(
30             _isa_str(@args) ? ( config_base => $args[0] ) : @args
31             );
32             };
33              
34             sub get_dbh {
35             my ($class_or_self, @args) = @_;
36             my $self;
37              
38             if ( blessed $class_or_self ) {
39             $self = $class_or_self;
40             $self->config_file( $args[0] ) if _isa_str(@args);
41             }
42             else {
43             $self = $class_or_self->new(
44             _isa_str(@args) ? ( config_file => $args[0] ) :
45             _has_odd_elm(@args) ? ( @args, undef ) : @args
46             );
47             }
48              
49             $self->_get_dbh(
50             _is_empty($self->config_file) ?
51             ( ref $args[0] ? $args[0] : [@args] ) : $self->_get_config
52             );
53             }
54              
55             sub _get_config {
56             my $self = shift;
57              
58             my ($file, $dir) = ($self->config_file, $self->config_base);
59             my $path
60             = ( _is_abs_path($file) or _is_empty($dir) ) ? $file :
61             join "/", $dir, $file ;
62              
63             Config::Any->load_files(
64             { files => [$path], use_ext => 1, flatten_to_hash => 1 }
65             )->{$path}
66             or confess "failed to read config file: $path\n";
67             }
68              
69             sub _get_dbh {
70             my ($self, $args) = @_;
71              
72             DBI->connect(
73             _isa_hashref($args) ? @$args{qw/ dsn userid passwd attr /} : @$args
74             );
75             }
76              
77             sub _isa_str { @_ == 1 and not ref $_[0] }
78              
79             sub _isa_hashref { ref $_[0] eq "HASH" }
80              
81             sub _is_abs_path { File::Spec->file_name_is_absolute($_[0]) }
82              
83             sub _is_empty { $_[0] eq q{} }
84              
85             sub _has_odd_elm { @_ % 2 }
86              
87             __PACKAGE__->meta->make_immutable;
88              
89             1; # End of DBIx::Factory
90              
91             __END__
92              
93             =head1 NAME
94              
95             DBIx::Factory - a simple factory class for DBI database handle
96              
97             =head1 SYNOPSIS
98              
99             # ... preparing to use ...
100              
101             $ cat > /config/base/dir/oracle/xe.yaml
102             userid: bahoo
103             passwd: typer
104             dsn: dbi:Oracle:XE
105             attr:
106             RaiseError: 0
107             PrintError: 1
108             LongReadLen: 2079152
109              
110             # ... and in your script ...
111              
112             # as a class method
113             my $dbh = DBIx::Factory->get_dbh(
114             config_base => "/config/base/dir",
115             config_file => "oracle/xe.yaml"
116             );
117              
118             # or simply...
119             # (in this case, $ENV{DBIF_BASE} is used as config_base.
120             # if not also defined $ENV{DBIF_BASE}, the argument specified
121             # is assumed as a relative path from your current directory)
122             my $dbh = DBIx::Factory->get_dbh("oracle/xe.yaml");
123              
124             # you can also specify it as an absolute path from '/'
125             # (and config_base is ignored even if it is specified)
126             my $dbh = DBIx::Factory->get_dbh("/config/base/dir/oracle/xe.yaml");
127              
128             # or you can even do just like DBI::connect
129             my $dbh = DBIx::Factory->get_dbh("dbi:Oracle:XE", "bahoo", "typer");
130              
131             # as an instance method
132             my $factory = DBIx::Factory->new("/config/base/dir");
133             my $dbh = $factory->get_dbh("oracle/xe.yaml");
134              
135             # when you set RaiseError attr to 1 in your config file
136             my $dbh = eval { $factory->get_dbh("oracle/xe.yaml") };
137             die $@ if $@;
138              
139             =head1 ABSTRACT
140              
141             When you release applications which use L<DBI>, you're putting
142             the same database connection info into different files every time,
143             aren't you? This module is useful for collecting up those info
144             into a single file, simplifying managing them, and also a little bit
145             simplifies making connection to the databases.
146              
147             =head1 PREPARATION
148              
149             After installation, you can first decide which directory is
150             the base directory where connection info files reside. Then,
151             you can create file(s) that contain database connection info,
152             one info per one file.
153              
154             Each connection info can be described in any format
155             which L<Config::Any> covers, parsed properly according to
156             the file extension, but must contain some items as follows:
157              
158             userid
159             passwd
160             dsn
161             attr
162              
163             These items must be hash keys that contain simple string values,
164             except C<attr> must contain hash for connection attributes such
165             as C<RaiseError>, C<AutoCommit> or so. See L</SYNOPSIS> for
166             a simple example.
167              
168             Created connection info file(s), you can place them under
169             the base directory. You can create any level of subdirectories
170             (such as "oracle", "host1/mysql" and so on) to simplify managing
171             those files.
172              
173             You can also place connection info file(s) anywhere else, when
174             you don't decide the base directory. In this case, you would
175             use connection info file(s) by specifying their absolute paths
176             from "/", or relative paths from your current directory.
177              
178             Besides, you can get connection without any connection info file,
179             by passing args to L</get_dbh> just like L<DBI::connect>.
180              
181             =head1 METHODS
182              
183             =head2 new
184              
185             Creates a new instance of DBIx::Factory. It can take one argument,
186             which is the base directory of the connection info files. If no
187             argument is specified, it assumes that C<$ENV{DBIF_BASE}> or
188             an empty string (which is later assumed as your current directory)
189             are specified as the base directory.
190              
191             When L</get_dbh> method is invoked as a class method, L</new>
192             will then be invoked internally.
193              
194             =head2 get_dbh
195              
196             There are two ways that you can invoke this method. The first is to
197             invoke this method as a class method. Doing so, this method will
198             take either hash argument which contains two keys, C<config_base>
199             (which is the base directory of the connection info files) and
200             C<config_file> (path from config_base to the specific connection
201             info file) with their values, or a simple string value which is
202             used as C<config_file>, while $ENV{DBIF_BASE} or an empty string
203             (if the $ENV is not defined) are used as C<config_base>.
204             Both C<config_base> and C<config_file> are passed to L</new> method
205             which will then be invoked.
206              
207             The second way is to invoke this method as an instance method.
208             Doing so, this method will take a single string argument which
209             is used as C<config_file>.
210              
211             Either way, please note that if you specify an absolute path
212             (which leads with '/') as C<config_file>, then C<config_base>
213             is always ignored.
214              
215             If the specified connection info file is unreadable,
216             this method will throw an exception. The same is true when C<RaiseError>
217             attribute is on and actually error happened while connecting to the
218             database.
219              
220             Besides, when invoking as either a class method or an instance method,
221             you can even pass the args just like when you call L<DBI::connect>.
222              
223             =head1 AUTHOR
224              
225             Bahootyper, C<< <bahootyper at gmail.com> >>
226              
227             =head1 BUGS
228              
229             Please report any bugs or feature requests, or funny english found
230             in this documentation to C<bug-dbix-factory at rt.cpan.org>,
231             or through the web interface at
232             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DBIx-Factory>.
233             I will be notified, and then you'll automatically be notified of
234             progress on your bug as I make changes.
235              
236             =head1 SUPPORT
237              
238             You can find documentation for this module with the perldoc command.
239              
240             perldoc DBIx::Factory
241              
242             You can also look for information at:
243              
244             =over 4
245              
246             =item * RT: CPAN's request tracker
247              
248             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBIx-Factory>
249              
250             =item * AnnoCPAN: Annotated CPAN documentation
251              
252             L<http://annocpan.org/dist/DBIx-Factory>
253              
254             =item * CPAN Ratings
255              
256             L<http://cpanratings.perl.org/d/DBIx-Factory>
257              
258             =item * Search CPAN
259              
260             L<http://search.cpan.org/dist/DBIx-Factory/>
261              
262             =back
263              
264             =head1 LICENSE AND COPYRIGHT
265              
266             Copyright 2010 Bahootyper.
267              
268             This program is free software; you can redistribute it and/or modify it
269             under the terms of either: the GNU General Public License as published
270             by the Free Software Foundation; or the Artistic License.
271              
272             See http://dev.perl.org/licenses/ for more information.