Commit | Line | Data |
75d07914 |
1 | package # hide from PAUSE |
c0e7b4e5 |
2 | DBIx::Class::Relationship::Accessor; |
4a07648a |
3 | |
4 | use strict; |
5 | use warnings; |
ddc0a6c8 |
6 | use Sub::Name (); |
4a07648a |
7 | |
044e70c7 |
8 | our %_pod_inherit_config = |
9 | ( |
10 | class_map => { 'DBIx::Class::Relationship::Accessor' => 'DBIx::Class::Relationship' } |
11 | ); |
12 | |
71e65b39 |
13 | sub register_relationship { |
14 | my ($class, $rel, $info) = @_; |
15 | if (my $acc_type = $info->{attrs}{accessor}) { |
223b8fe3 |
16 | $class->add_relationship_accessor($rel => $acc_type); |
4a07648a |
17 | } |
71e65b39 |
18 | $class->next::method($rel => $info); |
4a07648a |
19 | } |
20 | |
223b8fe3 |
21 | sub add_relationship_accessor { |
4a07648a |
22 | my ($class, $rel, $acc_type) = @_; |
23 | my %meth; |
24 | if ($acc_type eq 'single') { |
7a7e8718 |
25 | my $rel_info = $class->relationship_info($rel); |
4a07648a |
26 | $meth{$rel} = sub { |
27 | my $self = shift; |
28 | if (@_) { |
29 | $self->set_from_related($rel, @_); |
30 | return $self->{_relationship_data}{$rel} = $_[0]; |
31 | } elsif (exists $self->{_relationship_data}{$rel}) { |
32 | return $self->{_relationship_data}{$rel}; |
33 | } else { |
6d0ee587 |
34 | my $cond = $self->result_source->_resolve_condition( |
7a7e8718 |
35 | $rel_info->{cond}, $rel, $self |
84a1c93f |
36 | ); |
7a7e8718 |
37 | if ($rel_info->{attrs}->{undef_on_null_fk}){ |
e0d8aec0 |
38 | return undef unless ref($cond) eq 'HASH'; |
39 | return undef if grep { not defined $_ } values %$cond; |
7a7e8718 |
40 | } |
1a14aa3f |
41 | my $val = $self->find_related($rel, {}, {}); |
e0d8aec0 |
42 | return $val unless $val; # $val instead of undef so that null-objects can go through |
cde1c1e1 |
43 | |
b28cc0ba |
44 | return $self->{_relationship_data}{$rel} = $val; |
4a07648a |
45 | } |
46 | }; |
47 | } elsif ($acc_type eq 'filter') { |
701da8c4 |
48 | $class->throw_exception("No such column $rel to filter") |
103647d5 |
49 | unless $class->has_column($rel); |
4685e006 |
50 | my $f_class = $class->relationship_info($rel)->{class}; |
4a07648a |
51 | $class->inflate_column($rel, |
52 | { inflate => sub { |
53 | my ($val, $self) = @_; |
e60dc79f |
54 | return $self->find_or_new_related($rel, {}, {}); |
4a07648a |
55 | }, |
56 | deflate => sub { |
57 | my ($val, $self) = @_; |
701da8c4 |
58 | $self->throw_exception("$val isn't a $f_class") unless $val->isa($f_class); |
4a07648a |
59 | return ($val->_ident_values)[0]; |
60 | # WARNING: probably breaks for multi-pri sometimes. FIXME |
61 | } |
62 | } |
63 | ); |
64 | } elsif ($acc_type eq 'multi') { |
65 | $meth{$rel} = sub { shift->search_related($rel, @_) }; |
5b89a768 |
66 | $meth{"${rel}_rs"} = sub { shift->search_related_rs($rel, @_) }; |
4a07648a |
67 | $meth{"add_to_${rel}"} = sub { shift->create_related($rel, @_); }; |
68 | } else { |
701da8c4 |
69 | $class->throw_exception("No such relationship accessor type $acc_type"); |
4a07648a |
70 | } |
71 | { |
72 | no strict 'refs'; |
73 | no warnings 'redefine'; |
74 | foreach my $meth (keys %meth) { |
ddc0a6c8 |
75 | my $name = join '::', $class, $meth; |
76 | *$name = Sub::Name::subname($name, $meth{$meth}); |
4a07648a |
77 | } |
78 | } |
79 | } |
80 | |
81 | 1; |