File Coverage

blib/lib/DBIx/Class/Relationship/Accessor.pm
Criterion Covered Total %
statement 46 47 97.8
branch 15 22 68.1
condition 4 6 66.6
subroutine 9 9 100.0
pod 0 2 0.0
total 74 86 86.0


line stmt bran cond sub pod time code
1             package # hide from PAUSE
2             DBIx::Class::Relationship::Accessor;
3              
4 312     312   109472 use strict;
  312         771  
  312         8915  
5 312     312   1675 use warnings;
  312         684  
  312         7781  
6 312     312   1695 use DBIx::Class::Carp;
  312         648  
  312         1796  
7 312     312   1866 use DBIx::Class::_Util qw(quote_sub perlstring);
  312         759  
  312         15357  
8 312     312   1862 use namespace::clean;
  312         858  
  312         1790  
9              
10             our %_pod_inherit_config =
11             (
12             class_map => { 'DBIx::Class::Relationship::Accessor' => 'DBIx::Class::Relationship' }
13             );
14              
15             sub register_relationship {
16 23705     23705 0 67263 my ($class, $rel, $info) = @_;
17 23705 100       76279 if (my $acc_type = $info->{attrs}{accessor}) {
18 23702         138554 $class->add_relationship_accessor($rel => $acc_type);
19             }
20 23705         8420755 $class->next::method($rel => $info);
21             }
22              
23             sub add_relationship_accessor {
24 23702     23702 0 58251 my ($class, $rel, $acc_type) = @_;
25              
26 23702 100       84206 if ($acc_type eq 'single') {
    100          
    50          
27              
28 8916         40038 my @qsub_args = ( {}, {
29             attributes => [qw(
30             DBIC_method_is_single_relationship_accessor
31             DBIC_method_is_generated_from_resultsource_metadata
32             )]
33             });
34              
35              
36 8916         48089 quote_sub "${class}::${rel}" => sprintf(<<'EOC', perlstring $rel), @qsub_args;
37             my $self = shift;
38              
39             if (@_) {
40             $self->set_from_related( %1$s => @_ );
41             return $self->{_relationship_data}{%1$s} = $_[0];
42             }
43             elsif (exists $self->{_relationship_data}{%1$s}) {
44             return $self->{_relationship_data}{%1$s};
45             }
46             else {
47             my $rsrc = $self->result_source;
48              
49             my $jfc;
50              
51             return undef if (
52              
53             $rsrc->relationship_info(%1$s)->{attrs}{undef_on_null_fk}
54              
55             and
56              
57             $jfc = ( $rsrc->resolve_relationship_condition(
58             rel_name => %1$s,
59             foreign_alias => %1$s,
60             self_alias => 'me',
61             self_result_object => $self,
62             )->{join_free_condition} || {} )
63              
64             and
65              
66             grep { not defined $_ } values %%$jfc
67             );
68              
69             my $val = $self->related_resultset( %1$s )->single;
70             return $val unless $val; # $val instead of undef so that null-objects can go through
71              
72             return $self->{_relationship_data}{%1$s} = $val;
73             }
74             EOC
75             }
76             elsif ($acc_type eq 'filter') {
77              
78 4420         88374 my $rsrc = $class->result_source_instance;
79              
80 4420 50       138124 $rsrc->throw_exception("No such column '$rel' to filter")
81             unless $rsrc->has_column($rel);
82              
83 4420         73492 my $f_class = $rsrc->relationship_info($rel)->{class};
84              
85             $class->inflate_column($rel, {
86             inflate => sub {
87 309     309   1050 my ($val, $self) = @_;
88 309         1878 return $self->find_or_new_related($rel, {});
89             },
90             deflate => sub {
91 122     122   406 my ($val, $self) = @_;
92 122 50       1064 $self->throw_exception("'$val' isn't a $f_class") unless $val->isa($f_class);
93              
94             # MASSIVE FIXME - this code assumes we pointed at the PK, but the belongs_to
95             # helper does not check any of this
96             # fixup the code a bit to make things saner, but ideally 'filter' needs to
97             # be deprecated ASAP and removed shortly after
98             # Not doing so before 0.08250 however, too many things in motion already
99 122         606 my ($pk_col, @rest) = $val->result_source->_pri_cols_or_die;
100 122 50       453 $self->throw_exception(
101             "Relationship '$rel' of type 'filter' can not work with a multicolumn primary key on source '$f_class'"
102             ) if @rest;
103              
104 122         976 my $pk_val = $val->get_column($pk_col);
105 122 100 100     732 carp_unique (
106             "Unable to deflate 'filter'-type relationship '$rel' (related object "
107             . "primary key not retrieved), assuming undef instead"
108             ) if ( ! defined $pk_val and $val->in_storage );
109              
110 122         926 return $pk_val;
111             },
112 4420         88507 });
113              
114              
115             # god this is horrible...
116             my $acc =
117             $rsrc->columns_info->{$rel}{accessor}
118             ||
119 4420   33     109008 $rel
120             ;
121              
122             # because CDBI may elect to never make an accessor at all...
123 4420 50       29354 if( my $main_cref = $class->can($acc) ) {
124              
125 4420         19904 attributes->import(
126             $class,
127             $main_cref,
128             qw(
129             DBIC_method_is_filter_relationship_accessor
130             DBIC_method_is_generated_from_resultsource_metadata
131             ),
132             );
133              
134 4420 50       371092 if( my $extra_cref = $class->can("_${acc}_accessor") ) {
135 4420         16666 attributes->import(
136             $class,
137             $extra_cref,
138             qw(
139             DBIC_method_is_filter_relationship_extra_accessor
140             DBIC_method_is_generated_from_resultsource_metadata
141             ),
142             );
143             }
144             }
145             }
146             elsif ($acc_type eq 'multi') {
147              
148              
149 10366         48670 my @qsub_args = (
150             {},
151             {
152             attributes => [qw(
153             DBIC_method_is_multi_relationship_accessor
154             DBIC_method_is_generated_from_resultsource_metadata
155             DBIC_method_is_indirect_sugar
156             )]
157             },
158             );
159              
160              
161 10366         53263 quote_sub "${class}::${rel}", sprintf( <<'EOC', perlstring $rel ), @qsub_args;
162             DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and DBIx::Class::_Util::fail_on_internal_call;
163             shift->related_resultset(%s)->search( @_ )
164             EOC
165              
166              
167 10366 50       4415118 $qsub_args[1]{attributes}[0]
168             =~ s/^DBIC_method_is_multi_relationship_accessor$/DBIC_method_is_multi_relationship_extra_accessor/
169             or die "Unexpected attr '$qsub_args[1]{attributes}[0]' ...";
170              
171              
172 10366         53489 quote_sub "${class}::${rel}_rs", sprintf( <<'EOC', perlstring $rel ), @qsub_args;
173             DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and DBIx::Class::_Util::fail_on_internal_call;
174             shift->related_resultset(%s)->search_rs( @_ )
175             EOC
176              
177              
178 10366         4167043 quote_sub "${class}::add_to_${rel}", sprintf( <<'EOC', perlstring $rel ), @qsub_args;
179             DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and DBIx::Class::_Util::fail_on_internal_call;
180             shift->create_related( %s => @_ );
181             EOC
182              
183             }
184             else {
185 0           $class->throw_exception("No such relationship accessor type '$acc_type'");
186             }
187              
188             }
189              
190             1;