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 17     17   6738 use strict;
  17         34  
  17         434  
3 17     17   82 use warnings;
  17         25  
  17         372  
4 17     17   78 use parent "DBIx::DataModel::Meta";
  17         43  
  17         121  
5 17     17   1231 use DBIx::DataModel;
  17         147  
  17         104  
6 17         930 use DBIx::DataModel::Meta::Utils qw/define_class define_readonly_accessors
7 17     17   100 define_abstract_methods/;
  17         36  
8              
9 17     17   132 use Params::Validate qw/validate_with SCALAR ARRAYREF HASHREF OBJECT/;
  17         32  
  17         1066  
10 17     17   97 use Scalar::Util qw/weaken/;
  17         53  
  17         864  
11 17     17   93 use List::MoreUtils qw/any/;
  17         46  
  17         147  
12 17     17   9795 use Carp::Clan qw[^(DBIx::DataModel::|SQL::Abstract)];
  17         32  
  17         105  
13              
14 17     17   1367 use namespace::clean;
  17         39  
  17         118  
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 76     76   123 my $class = shift;
37 76         101 my $more_arg_spec = shift;
38 76         99 my $isa_slot = shift;
39              
40             # validation spec is built from a common part and a specific part
41 76         399 my %spec = (%common_arg_spec, %$more_arg_spec);
42              
43             # validate the parameters
44 76         2440 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 76   100     508 for my $attr (grep {($spec{$_}{type} || 0) & ARRAYREF} keys %spec) {
  814         1529  
52 228 100       433 next if not $self->{$attr};
53 183 50       382 $self->{$attr} = [$self->{$attr}] if not ref $self->{$attr};
54             }
55              
56             # the name is the short class name (before prepending the schema)
57 76         226 $self->{name} = $self->{class};
58              
59             # prepend schema name in class name, unless it already contains "::"
60             $self->{class} =~ s/^/$self->{schema}{class}::/
61 76 100       542 unless $self->{class} =~ /::/;
62              
63             # avoid circular references
64 76         310 weaken $self->{schema};
65              
66             # instanciate the metaclass
67 76         137 bless $self, $class;
68              
69             # build the list of parent classes
70 76         112 my @isa = map {$_->{class}} @{$self->{parents}};
  82         196  
  76         251  
71 76 50       173 if ($isa_slot) {
72 76         166 my $parent_class = $self->{schema}{$isa_slot}[0];
73             unshift @isa, $parent_class
74 76 100   80   405 unless any {$_->isa($parent_class)} @isa;
  80         427  
75             }
76              
77             # create the Perl class
78             define_class(
79             name => $self->{class},
80 76         422 isa => \@isa,
81             metadm => $self,
82             );
83              
84 76         333 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 369 my $self = shift;
96 293         326 my %seen;
97 293         562 my @pool = $self->parents;
98 293         384 my @result;
99 293         666 while (@pool) {
100 45         64 my $parent = shift @pool;
101 45 50       93 if (!$seen{$parent}){
102 45         73 $seen{$parent} = 1;
103 45         59 push @result, $parent;
104 45         81 push @pool, $parent->parents;
105             }
106             }
107 293         653 return @result;
108             }
109              
110              
111              
112              
113 36     36 0 89 sub path {shift->_consolidate_hash('path', @_)}
114 23     23 0 50 sub auto_insert_column {shift->_consolidate_hash('auto_insert_columns', @_)}
115 53     53 0 108 sub auto_update_column {shift->_consolidate_hash('auto_update_columns', @_)}
116 55     55 0 151 sub no_update_column {shift->_consolidate_hash('no_update_columns', @_)}
117              
118             sub _consolidate_hash {
119 289     289   498 my ($self, $field, $optional_hash_key) = @_;
120 289         359 my %hash;
121              
122 289         510 my @meta_sources = ($self, $self->ancestors, $self->{schema});
123              
124 289         446 foreach my $meta_source (reverse @meta_sources) {
125 611 100       771 while (my ($name, $val) = each %{$meta_source->{$field} || {}}) {
  1126         3522  
126 515 100       1066 $val ? $hash{$name} = $val : delete $hash{$name};
127             }
128             }
129 289 100       1087 return $optional_hash_key ? $hash{$optional_hash_key} : %hash;
130             }
131              
132              
133              
134             1;
135              
136