From: Justin Guenther Date: Sat, 17 Jun 2006 13:51:00 +0000 (+0000) Subject: added more many_to_many tests and changed add_to_rel to accept linking table column... X-Git-Tag: v0.07002~75^2~93^2~6 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=3bd6e3e0f621c4fe3d7562827a9b86ee5b91cbf2;p=dbsrgits%2FDBIx-Class.git added more many_to_many tests and changed add_to_rel to accept linking table column values --- diff --git a/lib/DBIx/Class/Relationship.pm b/lib/DBIx/Class/Relationship.pm index dd36166..9420ab7 100644 --- a/lib/DBIx/Class/Relationship.pm +++ b/lib/DBIx/Class/Relationship.pm @@ -216,29 +216,50 @@ relation names are then used in the many_to_many call. =head4 $rel +=over 4 + +=item Arguments: $vals?, $attrs + +=back + my $role_rs = $actor->roles; my $role1 = $actor->roles({ name => 'role1' })->first; -Returns a resultset for the table on the far-right side of the many-to-many -relationship. (e.g., in the above example, a CD's producers). +Returns a resultset for the foreign table on the right side of the +many-to-many relationship. (e.g., in the above example, a CD's +producers). Takes the same arguments as L. =head4 add_to_$rel +=over 4 + +=item Arguments: ($foreign_vals | $obj), $link_vals? + +=back + my $role = $schema->resultset('Role')->find(1); $actor->add_to_roles($role); # creates a My::DBIC::Schema::ActorRoles linking table row object - $actor->add_to_roles({ name => 'role1' }); - # creates a new My::DBIC::Schema::Role row object, as well as the - # linking table object + $actor->add_to_roles({ name => 'lead' }, { salary => 15_000_000 }); + # creates a new My::DBIC::Schema::Role row object and the linking table + # object with an extra column in the link -Adds a linking table object for the specified object, or if a hash is given -instead the related object is created before the linking table object is -created. +Adds a linking table object for C<$obj> or C<$foreign_vals>. If the first +argument is a hash reference, the related object is created first with the +column values in the hash. If an object reference is given, just the linking +table object is created. In either case, any additional column values for the +linking table object can be specified in C<$link_vals>. =head4 remove_from_$rel +=over 4 + +=item Arguments: $obj + +=back + my $role = $schema->resultset('Role')->find(1); $actor->remove_from_roles($role); # removes $role's My::DBIC::Schema::ActorRoles linking table row object diff --git a/lib/DBIx/Class/Relationship/ManyToMany.pm b/lib/DBIx/Class/Relationship/ManyToMany.pm index 8b29bf4..417c65d 100644 --- a/lib/DBIx/Class/Relationship/ManyToMany.pm +++ b/lib/DBIx/Class/Relationship/ManyToMany.pm @@ -35,8 +35,10 @@ sub many_to_many { my $obj = ref $_[0] ? ( ref $_[0] eq 'HASH' ? $f_rel_rs->create($_[0]) : $_[0] ) : ( $f_rel_rs->create({@_}) ); + my $link_vals = @_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {}; my $link = $self->search_related($rel)->new_result({}); $link->set_from_related($f_rel, $obj); + $link->set_columns($link_vals); $link->insert(); }; diff --git a/t/66relationship.t b/t/66relationship.t index 868ce15..5edbb34 100644 --- a/t/66relationship.t +++ b/t/66relationship.t @@ -7,7 +7,7 @@ use DBICTest; my $schema = DBICTest->init_schema(); -plan tests => 40; +plan tests => 49; # has_a test my $cd = $schema->resultset("CD")->find(4); @@ -154,6 +154,20 @@ like( $@, qr/needs an object/, 'remove_from_$rel($hash) dies correctly' ); eval { $cd->add_to_producers(); }; like( $@, qr/needs an object or hashref/, 'add_to_$rel(undef) dies correctly' ); +# many_to_many stresstest +my $twokey = $schema->resultset('TwoKeys')->find(1,1); +my $fourkey = $schema->resultset('FourKeys')->find(1,2,3,4); + +is( $twokey->fourkeys->count, 0, 'twokey has no fourkeys' ); +$twokey->add_to_fourkeys($fourkey, { autopilot => 'engaged' }); +my $got_fourkey = $twokey->fourkeys({ sensors => 'online' })->first; +is( $twokey->fourkeys->count, 1, 'twokey has one fourkey' ); +is( $got_fourkey->$_, $fourkey->$_, + 'fourkeys row has the correct value for column '.$_ ) + for (qw(foo bar hello goodbye sensors)); +$twokey->remove_from_fourkeys($fourkey); +is( $twokey->fourkeys->count, 0, 'twokey has no fourkeys' ); +is( $twokey->fourkeys_to_twokeys->count, 0, 'twokey has no links to fourkey' ); # test undirected many-to-many relationship (e.g. "related artists") my $undir_maps = $schema->resultset("Artist")->find(1)->artist_undirected_maps; diff --git a/t/lib/DBICTest.pm b/t/lib/DBICTest.pm index 9dbbf55..963eb4c 100755 --- a/t/lib/DBICTest.pm +++ b/t/lib/DBICTest.pm @@ -149,9 +149,9 @@ sub populate_schema { ]); $schema->populate('FourKeys', [ - [ qw/foo bar hello goodbye/ ], - [ 1, 2, 3, 4 ], - [ 5, 4, 3, 6 ], + [ qw/foo bar hello goodbye sensors/ ], + [ 1, 2, 3, 4, 'online' ], + [ 5, 4, 3, 6, 'offline' ], ]); $schema->populate('OneKey', [ diff --git a/t/lib/DBICTest/Schema.pm b/t/lib/DBICTest/Schema.pm index 72e1da6..9de55a1 100644 --- a/t/lib/DBICTest/Schema.pm +++ b/t/lib/DBICTest/Schema.pm @@ -24,6 +24,7 @@ __PACKAGE__->load_classes(qw/ /]}, ( 'FourKeys', + 'FourKeys_to_TwoKeys', '#dummy', 'SelfRef', 'ArtistUndirectedMap', diff --git a/t/lib/DBICTest/Schema/FourKeys.pm b/t/lib/DBICTest/Schema/FourKeys.pm index 71659e6..cdffa2f 100644 --- a/t/lib/DBICTest/Schema/FourKeys.pm +++ b/t/lib/DBICTest/Schema/FourKeys.pm @@ -9,7 +9,20 @@ DBICTest::Schema::FourKeys->add_columns( 'bar' => { data_type => 'integer' }, 'hello' => { data_type => 'integer' }, 'goodbye' => { data_type => 'integer' }, + 'sensors' => { data_type => 'character' }, ); DBICTest::Schema::FourKeys->set_primary_key(qw/foo bar hello goodbye/); +DBICTest::Schema::FourKeys->has_many( + 'fourkeys_to_twokeys', 'DBICTest::Schema::FourKeys_to_TwoKeys', { + 'foreign.f_foo' => 'self.foo', + 'foreign.f_bar' => 'self.bar', + 'foreign.f_hello' => 'self.hello', + 'foreign.f_goodbye' => 'self.goodbye', +}); + +DBICTest::Schema::FourKeys->many_to_many( + 'twokeys', 'fourkeys_to_twokeys', 'twokeys', +); + 1; diff --git a/t/lib/DBICTest/Schema/FourKeys_to_TwoKeys.pm b/t/lib/DBICTest/Schema/FourKeys_to_TwoKeys.pm new file mode 100644 index 0000000..6e86313 --- /dev/null +++ b/t/lib/DBICTest/Schema/FourKeys_to_TwoKeys.pm @@ -0,0 +1,32 @@ +package # hide from PAUSE + DBICTest::Schema::FourKeys_to_TwoKeys; + +use base 'DBIx::Class::Core'; + +__PACKAGE__->table('fourkeys_to_twokeys'); +__PACKAGE__->add_columns( + 'f_foo' => { data_type => 'integer' }, + 'f_bar' => { data_type => 'integer' }, + 'f_hello' => { data_type => 'integer' }, + 'f_goodbye' => { data_type => 'integer' }, + 't_artist' => { data_type => 'integer' }, + 't_cd' => { data_type => 'integer' }, + 'autopilot' => { data_type => 'character' }, +); +__PACKAGE__->set_primary_key( + qw/f_foo f_bar f_hello f_goodbye t_artist t_cd/ +); + +__PACKAGE__->belongs_to('fourkeys', 'DBICTest::Schema::FourKeys', { + 'foreign.foo' => 'self.f_foo', + 'foreign.bar' => 'self.f_bar', + 'foreign.hello' => 'self.f_hello', + 'foreign.goodbye' => 'self.f_goodbye', +}); + +__PACKAGE__->belongs_to('twokeys', 'DBICTest::Schema::TwoKeys', { + 'foreign.artist' => 'self.t_artist', + 'foreign.cd' => 'self.t_cd', +}); + +1; diff --git a/t/lib/DBICTest/Schema/TwoKeys.pm b/t/lib/DBICTest/Schema/TwoKeys.pm index 8483d0b..7bb1965 100755 --- a/t/lib/DBICTest/Schema/TwoKeys.pm +++ b/t/lib/DBICTest/Schema/TwoKeys.pm @@ -13,4 +13,14 @@ __PACKAGE__->set_primary_key(qw/artist cd/); __PACKAGE__->belongs_to( artist => 'DBICTest::Schema::Artist' ); __PACKAGE__->belongs_to( cd => 'DBICTest::Schema::CD' ); +__PACKAGE__->has_many( + 'fourkeys_to_twokeys', 'DBICTest::Schema::FourKeys_to_TwoKeys', { + 'foreign.t_artist' => 'self.artist', + 'foreign.t_cd' => 'self.cd', +}); + +__PACKAGE__->many_to_many( + 'fourkeys', 'fourkeys_to_twokeys', 'fourkeys', +); + 1; diff --git a/t/lib/sqlite.sql b/t/lib/sqlite.sql index d7fa393..551d159 100644 --- a/t/lib/sqlite.sql +++ b/t/lib/sqlite.sql @@ -1,6 +1,6 @@ -- -- Created by SQL::Translator::Producer::SQLite --- Created on Sat May 27 21:28:05 2006 +-- Created on Sat Jun 17 07:46:56 2006 -- BEGIN TRANSACTION; @@ -23,14 +23,6 @@ CREATE TABLE serialized ( ); -- --- Table: liner_notes --- -CREATE TABLE liner_notes ( - liner_id INTEGER PRIMARY KEY NOT NULL, - notes varchar(100) NOT NULL -); - --- -- Table: cd_to_producer -- CREATE TABLE cd_to_producer ( @@ -40,6 +32,14 @@ CREATE TABLE cd_to_producer ( ); -- +-- Table: liner_notes +-- +CREATE TABLE liner_notes ( + liner_id INTEGER PRIMARY KEY NOT NULL, + notes varchar(100) NOT NULL +); + +-- -- Table: artist -- CREATE TABLE artist ( @@ -48,6 +48,20 @@ CREATE TABLE artist ( ); -- +-- Table: fourkeys_to_twokeys +-- +CREATE TABLE fourkeys_to_twokeys ( + f_foo integer NOT NULL, + f_bar integer NOT NULL, + f_hello integer NOT NULL, + f_goodbye integer NOT NULL, + t_artist integer NOT NULL, + t_cd integer NOT NULL, + autopilot character NOT NULL, + PRIMARY KEY (f_foo, f_bar, f_hello, f_goodbye, t_artist, t_cd) +); + +-- -- Table: twokeytreelike -- CREATE TABLE twokeytreelike ( @@ -97,28 +111,19 @@ CREATE TABLE track ( ); -- --- Table: self_ref +-- Table: treelike -- -CREATE TABLE self_ref ( +CREATE TABLE treelike ( id INTEGER PRIMARY KEY NOT NULL, + parent integer NOT NULL, name varchar(100) NOT NULL ); -- --- Table: tags --- -CREATE TABLE tags ( - tagid INTEGER PRIMARY KEY NOT NULL, - cd integer NOT NULL, - tag varchar(100) NOT NULL -); - --- --- Table: treelike +-- Table: self_ref -- -CREATE TABLE treelike ( +CREATE TABLE self_ref ( id INTEGER PRIMARY KEY NOT NULL, - parent integer NOT NULL, name varchar(100) NOT NULL ); @@ -132,6 +137,15 @@ CREATE TABLE link ( ); -- +-- Table: tags +-- +CREATE TABLE tags ( + tagid INTEGER PRIMARY KEY NOT NULL, + cd integer NOT NULL, + tag varchar(100) NOT NULL +); + +-- -- Table: event -- CREATE TABLE event ( @@ -156,6 +170,7 @@ CREATE TABLE fourkeys ( bar integer NOT NULL, hello integer NOT NULL, goodbye integer NOT NULL, + sensors character NOT NULL, PRIMARY KEY (foo, bar, hello, goodbye) ); @@ -169,6 +184,14 @@ CREATE TABLE artist_undirected_map ( ); -- +-- Table: producer +-- +CREATE TABLE producer ( + producerid INTEGER PRIMARY KEY NOT NULL, + name varchar(100) NOT NULL +); + +-- -- Table: onekey -- CREATE TABLE onekey ( @@ -177,14 +200,6 @@ CREATE TABLE onekey ( cd integer NOT NULL ); --- --- Table: producer --- -CREATE TABLE producer ( - producerid INTEGER PRIMARY KEY NOT NULL, - name varchar(100) NOT NULL -); - CREATE UNIQUE INDEX tktlnameunique_twokeytreelike on twokeytreelike (name); CREATE UNIQUE INDEX cd_artist_title_cd on cd (artist, title); CREATE UNIQUE INDEX prod_name_producer on producer (name);