fixed up sqlt tests a bit and tried fixing 2 failing sqlt tests
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Relationship / ManyToMany.pm
1 package # hide from PAUSE
2     DBIx::Class::Relationship::ManyToMany;
3
4 use strict;
5 use warnings;
6
7 sub many_to_many {
8   my ($class, $meth, $rel, $f_rel, $rel_attrs) = @_;
9   {
10     no strict 'refs';
11     no warnings 'redefine';
12
13     my $remove_link_meth = "remove_from_$rel";
14     my $add_link_meth = "add_to_$rel";
15
16     *{"${class}::${meth}"} = sub {
17       my $self = shift;
18       my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {};
19       $self->search_related($rel)->search_related(
20         $f_rel, @_ > 0 ? @_ : undef, { %{$rel_attrs||{}}, %$attrs }
21       );
22     };
23
24     *{"${class}::add_to_${meth}"} = sub {
25       my $self = shift;
26       @_ > 0 or $self->throw_exception(
27         "$add_link_meth needs an object or hashref"
28       );
29       my $source = $self->result_source;
30       my $schema = $source->schema;
31       my $rel_source_name = $source->relationship_info($rel)->{source};
32       my $rel_source = $schema->resultset($rel_source_name)->result_source;
33       my $f_rel_source_name = $rel_source->relationship_info($f_rel)->{source};
34       my $f_rel_rs = $schema->resultset($f_rel_source_name);
35       my $obj = ref $_[0]
36         ? ( ref $_[0] eq 'HASH' ? $f_rel_rs->create($_[0]) : $_[0] )
37         : ( $f_rel_rs->create({@_}) );
38       my $link_vals = @_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {};
39       my $link = $self->search_related($rel)->new_result({});
40       $link->set_from_related($f_rel, $obj);
41       $link->set_columns($link_vals);
42       $link->insert();
43     };
44
45     *{"${class}::remove_from_${meth}"} = sub {
46       my $self = shift;
47       @_ > 0 && ref $_[0] ne 'HASH'
48         or $self->throw_exception("$remove_link_meth needs an object");
49       my $obj = shift;
50       my $rel_source = $self->search_related($rel)->result_source;
51       my $cond = $rel_source->relationship_info($f_rel)->{cond};
52       my $link_cond = $rel_source->resolve_condition(
53         $cond, $obj, $f_rel
54       );
55       $self->search_related($rel, $link_cond)->delete;
56     };
57
58   }
59 }
60
61 1;