File Coverage

blib/lib/DBIx/DataModel/Meta/Source.pm
Criterion Covered Total %
statement 75 75 100.0
branch 15 18 83.3
condition 2 2 100.0
subroutine 18 18 100.0
pod 0 5 0.0
total 110 118 93.2


line stmt bran cond sub pod time code
1             package DBIx::DataModel::Meta::Source;
2 18     18   8382 use strict;
  18         40  
  18         523  
3 18     18   97 use warnings;
  18         40  
  18         449  
4 18     18   91 use parent "DBIx::DataModel::Meta";
  18         44  
  18         161  
5 18     18   1464 use DBIx::DataModel;
  18         194  
  18         122  
6 18         1218 use DBIx::DataModel::Meta::Utils qw/define_class define_readonly_accessors
7 18     18   114 define_abstract_methods/;
  18         36  
8              
9 18     18   168 use Params::Validate qw/validate_with SCALAR ARRAYREF HASHREF OBJECT/;
  18         49  
  18         1276  
10 18     18   113 use Scalar::Util qw/weaken/;
  18         44  
  18         1112  
11 18     18   126 use List::MoreUtils qw/any/;
  18         33  
  18         199  
12 18     18   12515 use Carp::Clan qw[^(DBIx::DataModel::|SQL::Abstract)];
  18         38  
  18         113  
13              
14 18     18   1729 use namespace::clean;
  18         44  
  18         121  
15              
16             #----------------------------------------------------------------------
17             # COMPILE-TIME METHODS
18             #----------------------------------------------------------------------
19              
20             my %common_arg_spec = (
21             schema => {isa => "DBIx::DataModel::Meta::Schema"},
22             class => {type => SCALAR},
23             default_columns => {type => SCALAR, default => "*"},
24             parents => {type => OBJECT|ARRAYREF, default => [] },
25             primary_key => {type => SCALAR|ARRAYREF, default => [] },
26             aliased_tables => {type => HASHREF, default => {} }, # for joins
27              
28             # other slot filled later : 'name'
29             );
30              
31              
32             define_readonly_accessors(__PACKAGE__, keys %common_arg_spec, 'name');
33             define_abstract_methods (__PACKAGE__, qw/db_from where/);
34              
35             sub _new_meta_source { # called by new() in Meta::Table and Meta::Join
36 79     79   166 my $class = shift;
37 79         133 my $more_arg_spec = shift;
38 79         127 my $isa_slot = shift;
39              
40             # validation spec is built from a common part and a specific part
41 79         516 my %spec = (%common_arg_spec, %$more_arg_spec);
42              
43             # validate the parameters
44 79         3218 my $self = validate_with(
45             params => \@_,
46             spec => \%spec,
47             allow_extra => 0,
48             );
49              
50             # force into arrayref if accepts ARRAYREF but given as scalar
51 79   100     658 for my $attr (grep {($spec{$_}{type} || 0) & ARRAYREF} keys %spec) {
  853         1976  
52 237 100       552 next if not $self->{$attr};
53 189 50       497 $self->{$attr} = [$self->{$attr}] if not ref $self->{$attr};
54             }
55              
56             # the name is the short class name (before prepending the schema)
57 79         286 $self->{name} = $self->{class};
58              
59             # prepend schema name in class name, unless it already contains "::"
60             $self->{class} =~ s/^/$self->{schema}{class}::/
61 79 100       610 unless $self->{class} =~ /::/;
62              
63             # avoid circular references
64 79         370 weaken $self->{schema};
65              
66             # instanciate the metaclass
67 79         164 bless $self, $class;
68              
69             # build the list of parent classes
70 79         138 my @isa = map {$_->{class}} @{$self->{parents}};
  82         246  
  79         327  
71 79 50       221 if ($isa_slot) {
72 79         219 my $parent_class = $self->{schema}{$isa_slot}[0];
73             unshift @isa, $parent_class
74 79 100   80   518 unless any {$_->isa($parent_class)} @isa;
  80         564  
75             }
76              
77             # create the Perl class
78             define_class(
79             name => $self->{class},
80 79         593 isa => \@isa,
81             metadm => $self,
82             );
83              
84 79         409 return $self;
85             }
86              
87              
88             #----------------------------------------------------------------------
89             # RUN-TIME METHODS
90             #----------------------------------------------------------------------
91              
92              
93              
94             sub ancestors { # walk through parent metaobjects, similar to C3 inheritance
95 293     293 0 472 my $self = shift;
96 293         430 my %seen;
97 293         764 my @pool = $self->parents;
98 293         485 my @result;
99 293         729 while (@pool) {
100 45         85 my $parent = shift @pool;
101 45 50       123 if (!$seen{$parent}){
102 45         100 $seen{$parent} = 1;
103 45         78 push @result, $parent;
104 45         99 push @pool, $parent->parents;
105             }
106             }
107 293         843 return @result;
108             }
109              
110              
111              
112              
113 36     36 0 118 sub path {shift->_consolidate_hash('path', @_)}
114 23     23 0 64 sub auto_insert_column {shift->_consolidate_hash('auto_insert_columns', @_)}
115 53     53 0 135 sub auto_update_column {shift->_consolidate_hash('auto_update_columns', @_)}
116 55     55 0 171 sub no_update_column {shift->_consolidate_hash('no_update_columns', @_)}
117              
118             sub _consolidate_hash {
119 289     289   636 my ($self, $field, $optional_hash_key) = @_;
120 289         437 my %hash;
121              
122 289         648 my @meta_sources = ($self, $self->ancestors, $self->{schema});
123              
124 289         583 foreach my $meta_source (reverse @meta_sources) {
125 611 100       928 while (my ($name, $val) = each %{$meta_source->{$field} || {}}) {
  1126         4313  
126 515 100       1317 $val ? $hash{$name} = $val : delete $hash{$name};
127             }
128             }
129 289 100       1342 return $optional_hash_key ? $hash{$optional_hash_key} : %hash;
130             }
131              
132              
133              
134             1;
135              
136