File Coverage

blib/lib/DBIx/DataModel/Meta/Path.pm
Criterion Covered Total %
statement 46 46 100.0
branch 5 6 83.3
condition n/a
subroutine 12 12 100.0
pod 2 2 100.0
total 65 66 98.4


line stmt bran cond sub pod time code
1             package DBIx::DataModel::Meta::Path;
2 14     14   7236 use strict;
  14         28  
  14         372  
3 14     14   62 use warnings;
  14         27  
  14         346  
4 14     14   63 use parent "DBIx::DataModel::Meta";
  14         53  
  14         68  
5 14     14   728 use DBIx::DataModel;
  14         23  
  14         61  
6 14     14   79 use DBIx::DataModel::Meta::Utils qw/define_readonly_accessors/;
  14         42  
  14         728  
7              
8 14     14   84 use Scalar::Util qw/looks_like_number weaken/;
  14         22  
  14         721  
9 14     14   82 use Params::Validate qw/validate_with SCALAR HASHREF ARRAYREF OBJECT/;
  14         28  
  14         869  
10 14     14   83 use Carp::Clan qw[^(DBIx::DataModel::|SQL::Abstract)];
  14         28  
  14         74  
11 14     14   1215 use namespace::clean;
  14         32  
  14         73  
12              
13 14     14   3886 {no strict 'refs'; *CARP_NOT = \@DBIx::DataModel::CARP_NOT;}
  14         25  
  14         5238  
14              
15             my $path_spec = {
16             name => {type => SCALAR},
17             from => {isa => 'DBIx::DataModel::Meta::Source::Table'},
18             to => {isa => 'DBIx::DataModel::Meta::Source::Table'},
19             on => {type => HASHREF}, # join condition
20             multiplicity => {type => ARRAYREF},
21             association => {type => OBJECT,
22             isa => "DBIx::DataModel::Meta::Association"},
23             direction => {type => SCALAR, regex => qr/^(AB|BA)$/},
24             };
25              
26             sub new {
27 54     54 1 85 my $class = shift;
28              
29             # parse arguments and create $self
30 54         1140 my $self = validate_with(
31             params => \@_,
32             spec => $path_spec,
33             allow_extra => 0,
34             );
35              
36 54         1222 my $path = $self->{name};
37 54         261 weaken $self->{$_} for qw/from to association/;
38              
39             # add this path into the 'from' metaclass
40 54 50       157 not $self->{from}{path}{$path}
41             or croak "$self->{from}{class} already has a path '$path'";
42 54         102 $self->{from}{path}{$path} = $self;
43 26         70 push @{$self->{from}{components}}, $path
44 54 100       120 if $self->{association}{kind} eq 'Composition';
45              
46             # install a navigation method into the 'from' table class
47             my @navigation_args = ($self->{name}, # method name
48 54         117 $self->{name}); # path to follow
49             push @navigation_args, {-result_as => "firstrow"}
50 54 100       139 if $self->{multiplicity}[1] == 1;
51 54         174 $self->{from}->define_navigation_method(@navigation_args);
52              
53 54         230 bless $self, $class;
54             }
55              
56             define_readonly_accessors(__PACKAGE__, keys %$path_spec);
57              
58              
59             sub opposite {
60 3     3 1 1221 my $self = shift;
61 3         10 my $opposite_direction = reverse $self->direction;
62 3         5 my $opposite_path = "path_".$opposite_direction;
63 3         9 return $self->association->$opposite_path;
64             }
65              
66              
67             1;
68              
69              
70             __END__