File Coverage

blib/lib/App/DBCritic.pm
Criterion Covered Total %
statement 61 70 87.1
branch 4 10 40.0
condition 2 3 66.6
subroutine 17 19 89.4
pod 1 1 100.0
total 85 103 82.5


line stmt bran cond sub pod time code
1             package App::DBCritic;
2              
3 7     7   678370 use strict;
  7         12  
  7         238  
4 7     7   3402 use utf8;
  7         53  
  7         33  
5 7     7   235 use Modern::Perl '2011'; ## no critic (Modules::ProhibitUseQuotedVersion)
  7         8  
  7         47  
6              
7             our $VERSION = '0.021'; # TRIAL VERSION
8 7     7   1011 use Carp;
  7         9  
  7         415  
9 7     7   1608 use English '-no_match_vars';
  7         7136  
  7         44  
10 7     7   6150 use List::MoreUtils 'any';
  7         6460  
  7         594  
11             use Module::Pluggable
12 7         57 search_path => [ __PACKAGE__ . '::Policy' ],
13             sub_name => 'policies',
14 7     7   3425 instantiate => 'new';
  7         52446  
15 7     7   5085 use Moo;
  7         78504  
  7         44  
16 7     7   9922 use Scalar::Util 'blessed';
  7         74  
  7         417  
17 7     7   2781 use App::DBCritic::Loader;
  7         24  
  7         49  
18              
19             for (qw(username password class_name)) { has $ARG => ( is => 'ro' ) }
20              
21             has dsn => ( is => 'ro', lazy => 1, default => \&_build_dsn );
22              
23             sub _build_dsn {
24 0     0   0 my $self = shift;
25              
26             ## no critic (ValuesAndExpressions::ProhibitAccessOfPrivateData)
27 0         0 my $dbh = $self->schema->storage->dbh;
28 0         0 return join q{:} => 'dbi', $dbh->{Driver}{Name}, $dbh->{Name};
29             }
30              
31             has schema => (
32             is => 'ro',
33             coerce => 1,
34             lazy => 1,
35             default => \&_build_schema,
36             coerce => \&_coerce_schema,
37             );
38              
39             sub _build_schema {
40 1     1   446 my $self = shift;
41              
42 1         3 my @connect_info = map { $self->$ARG } qw(dsn username password);
  3         418  
43              
44 1 50       6 if ( my $class_name = $self->class_name ) {
45 0 0       0 return $class_name->connect(@connect_info)
46             if eval "require $class_name";
47             }
48              
49 1         5 return _coerce_schema( \@connect_info );
50             }
51              
52             sub _coerce_schema {
53 7     7   2266744 my $schema = shift;
54              
55 7 100 66     466 return $schema if blessed $schema and $schema->isa('DBIx::Class::Schema');
56              
57             local $SIG{__WARN__} = sub {
58 0 0   0   0 if ( $ARG[0] !~ / has no primary key at /ms ) {
59 0         0 print {*STDERR} $ARG[0];
  0         0  
60             }
61 1         8 };
62 1 50       4 return App::DBCritic::Loader->connect( @{$schema} )
  1         15  
63             if 'ARRAY' eq ref $schema;
64             ## no critic (ErrorHandling::RequireUseOfExceptions)
65 0         0 croak q{don't know how to make a schema from a } . ref $schema;
66             }
67              
68             has _elements => ( is => 'ro', lazy => 1, default => \&_build__elements );
69              
70             sub _build__elements {
71 5     5   1814 my $self = shift;
72 5         20 my $schema = $self->schema;
73             return {
74 7         283 Schema => [$schema],
75 7         3031 ResultSource => [ map { $schema->source($ARG) } $schema->sources ],
76 5         1941 ResultSet => [ map { $schema->resultset($ARG) } $schema->sources ],
77             };
78             }
79              
80             sub critique {
81 1     1 1 2 for ( @{ shift->violations } ) {say}
  1         5  
  0         0  
82 1         32 return;
83             }
84              
85             has violations => (
86             is => 'ro',
87             lazy => 1,
88             default => sub {
89             my $self = shift;
90             [ map { $self->_policy_loop( $ARG, $self->_elements->{$ARG} ) }
91             keys %{ $self->_elements },
92             ];
93             },
94             );
95              
96             sub _policy_loop {
97 15     15   164 my ( $self, $policy_type, $elements_ref ) = @_;
98 15         25 my @violations;
99 15         81 for my $policy ( grep { _policy_applies_to( $ARG, $policy_type ) }
  60         85281  
100             $self->policies )
101             {
102 4         1643 push @violations, grep {$ARG}
  28         5504  
103 20         27 map { $policy->violates( $ARG, $self->schema ) } @{$elements_ref};
  20         37  
104             }
105 15         227 return @violations;
106             }
107              
108             sub _policy_applies_to {
109 60     60   91 my ( $policy, $type ) = @_;
110 60     60   178 return any { $ARG eq $type } @{ $policy->applies_to };
  60         15331  
  60         187  
111             }
112              
113             1;
114              
115             # ABSTRACT: Critique a database schema for best practices
116              
117             __END__