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 20     20   10918 use strict;
  20         45  
  20         774  
3 20     20   96 use warnings;
  20         35  
  20         971  
4 20     20   99 use parent "DBIx::DataModel::Meta";
  20         32  
  20         220  
5 20     20   1528 use DBIx::DataModel;
  20         34  
  20         160  
6 20         1448 use DBIx::DataModel::Meta::Utils qw/define_class define_readonly_accessors
7 20     20   104 define_abstract_methods/;
  20         37  
8 20     20   104 use DBIx::DataModel::Carp;
  20         35  
  20         114  
9              
10 20     20   1165 use Params::Validate qw/validate_with SCALAR ARRAYREF HASHREF OBJECT/;
  20         74  
  20         1431  
11 20     20   108 use Scalar::Util qw/weaken/;
  20         40  
  20         1132  
12 20     20   109 use List::MoreUtils qw/any/;
  20         45  
  20         232  
13              
14 20     20   16217 use namespace::clean;
  20         43  
  20         130  
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 85     85   161 my $class = shift;
37 85         148 my $more_arg_spec = shift;
38 85         139 my $isa_slot = shift;
39              
40             # validation spec is built from a common part and a specific part
41 85         667 my %spec = (%common_arg_spec, %$more_arg_spec);
42              
43             # validate the parameters
44 85         3829 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 85   100     758 for my $attr (grep {($spec{$_}{type} || 0) & ARRAYREF} keys %spec) {
  945         2282  
52 255 100       562 next if not $self->{$attr};
53 204 50       560 $self->{$attr} = [$self->{$attr}] if not ref $self->{$attr};
54             }
55              
56             # the name is the short class name (before prepending the schema)
57 85         342 $self->{name} = $self->{class};
58              
59             # prepend schema name in class name, unless it already contains "::"
60             $self->{class} =~ s/^/$self->{schema}{class}::/
61 85 100       678 unless $self->{class} =~ /::/;
62              
63             # avoid circular references
64 85         217 weaken $self->{schema};
65              
66             # instanciate the metaclass
67 85         242 bless $self, $class;
68              
69             # build the list of parent classes
70 85         140 my @isa = map {$_->{class}} @{$self->{parents}};
  90         275  
  85         423  
71 85 50       221 if ($isa_slot) {
72 85         280 my $parent_class = $self->{schema}{$isa_slot}[0];
73             unshift @isa, $parent_class
74 85 100   88   660 unless any {$_->isa($parent_class)} @isa;
  88         672  
75             }
76              
77             # create the Perl class
78             define_class(
79             name => $self->{class},
80 85         643 isa => \@isa,
81             metadm => $self,
82             );
83              
84 85         497 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 301     301 0 479 my $self = shift;
96 301         406 my %seen;
97 301         828 my @pool = $self->parents;
98 301         498 my @result;
99 301         770 while (@pool) {
100 49         71 my $parent = shift @pool;
101 49 50       119 if (!$seen{$parent}){
102 49         102 $seen{$parent} = 1;
103 49         71 push @result, $parent;
104 49         108 push @pool, $parent->parents;
105             }
106             }
107 301         892 return @result;
108             }
109              
110              
111              
112              
113 38     38 0 137 sub path {shift->_consolidate_hash('path', @_)}
114 23     23 0 63 sub auto_insert_column {shift->_consolidate_hash('auto_insert_columns', @_)}
115 53     53 0 129 sub auto_update_column {shift->_consolidate_hash('auto_update_columns', @_)}
116 55     55 0 206 sub no_update_column {shift->_consolidate_hash('no_update_columns', @_)}
117              
118             sub _consolidate_hash {
119 297     297   824 my ($self, $field, $optional_hash_key) = @_;
120 297         446 my %hash;
121              
122 297         749 my @meta_sources = ($self, $self->ancestors, $self->{schema});
123              
124 297         561 foreach my $meta_source (reverse @meta_sources) {
125 631 100       929 while (my ($name, $val) = each %{$meta_source->{$field} || {}}) {
  1158         4686  
126 527 100       1446 $val ? $hash{$name} = $val : delete $hash{$name};
127             }
128             }
129 297 100       1525 return $optional_hash_key ? $hash{$optional_hash_key} : %hash;
130             }
131              
132              
133              
134             1;
135              
136