Commit | Line | Data |
75d07914 |
1 | package # hide from PAUSE |
c0e7b4e5 |
2 | DBIx::Class::Relationship::Accessor; |
4a07648a |
3 | |
4 | use strict; |
5 | use warnings; |
6 | |
71e65b39 |
7 | sub register_relationship { |
8 | my ($class, $rel, $info) = @_; |
9 | if (my $acc_type = $info->{attrs}{accessor}) { |
223b8fe3 |
10 | $class->add_relationship_accessor($rel => $acc_type); |
4a07648a |
11 | } |
71e65b39 |
12 | $class->next::method($rel => $info); |
4a07648a |
13 | } |
14 | |
223b8fe3 |
15 | sub add_relationship_accessor { |
4a07648a |
16 | my ($class, $rel, $acc_type) = @_; |
17 | my %meth; |
18 | if ($acc_type eq 'single') { |
19 | $meth{$rel} = sub { |
20 | my $self = shift; |
21 | if (@_) { |
22 | $self->set_from_related($rel, @_); |
23 | return $self->{_relationship_data}{$rel} = $_[0]; |
24 | } elsif (exists $self->{_relationship_data}{$rel}) { |
25 | return $self->{_relationship_data}{$rel}; |
26 | } else { |
1a14aa3f |
27 | my $val = $self->find_related($rel, {}, {}); |
b28cc0ba |
28 | return unless $val; |
29 | return $self->{_relationship_data}{$rel} = $val; |
4a07648a |
30 | } |
31 | }; |
32 | } elsif ($acc_type eq 'filter') { |
701da8c4 |
33 | $class->throw_exception("No such column $rel to filter") |
103647d5 |
34 | unless $class->has_column($rel); |
4685e006 |
35 | my $f_class = $class->relationship_info($rel)->{class}; |
4a07648a |
36 | $class->inflate_column($rel, |
37 | { inflate => sub { |
38 | my ($val, $self) = @_; |
39 | return $self->find_or_create_related($rel, {}, {}); |
40 | }, |
41 | deflate => sub { |
42 | my ($val, $self) = @_; |
701da8c4 |
43 | $self->throw_exception("$val isn't a $f_class") unless $val->isa($f_class); |
4a07648a |
44 | return ($val->_ident_values)[0]; |
45 | # WARNING: probably breaks for multi-pri sometimes. FIXME |
46 | } |
47 | } |
48 | ); |
49 | } elsif ($acc_type eq 'multi') { |
50 | $meth{$rel} = sub { shift->search_related($rel, @_) }; |
5b89a768 |
51 | $meth{"${rel}_rs"} = sub { shift->search_related_rs($rel, @_) }; |
4a07648a |
52 | $meth{"add_to_${rel}"} = sub { shift->create_related($rel, @_); }; |
53 | } else { |
701da8c4 |
54 | $class->throw_exception("No such relationship accessor type $acc_type"); |
4a07648a |
55 | } |
56 | { |
57 | no strict 'refs'; |
58 | no warnings 'redefine'; |
59 | foreach my $meth (keys %meth) { |
60 | *{"${class}::${meth}"} = $meth{$meth}; |
61 | } |
62 | } |
63 | } |
64 | |
096f4212 |
65 | sub new { |
66 | my ($class, $attrs, @rest) = @_; |
67 | my ($related, $info); |
68 | foreach my $key (keys %{$attrs||{}}) { |
69 | next unless $info = $class->relationship_info($key); |
70 | $related->{$key} = delete $attrs->{$key} |
71 | if ref $attrs->{$key} |
72 | && $info->{attrs}{accessor} |
73 | && $info->{attrs}{accessor} eq 'single'; |
74 | } |
75 | my $obj = $class->next::method($attrs, @rest); |
76 | if ($related) { |
77 | $obj->{_relationship_data} = $related; |
78 | foreach my $rel (keys %$related) { |
79 | $obj->set_from_related($rel, $related->{$rel}); |
80 | } |
81 | } |
82 | return $obj; |
83 | } |
84 | |
85 | sub update { |
86 | my ($obj, $attrs, @rest) = @_; |
87 | my $info; |
88 | foreach my $key (keys %{$attrs||{}}) { |
89 | next unless $info = $obj->relationship_info($key); |
90 | if (ref $attrs->{$key} && $info->{attrs}{accessor} |
91 | && $info->{attrs}{accessor} eq 'single') { |
92 | my $rel = delete $attrs->{$key}; |
93 | $obj->set_from_related($key => $rel); |
94 | $obj->{_relationship_data}{$key} = $rel; |
95 | } |
96 | } |
97 | return $obj->next::method($attrs, @rest); |
98 | } |
99 | |
4a07648a |
100 | 1; |