=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<DBIx::Class::ResultSet/"search">.
=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
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();
};
my $schema = DBICTest->init_schema();
-plan tests => 40;
+plan tests => 49;
# has_a test
my $cd = $schema->resultset("CD")->find(4);
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;
]);
$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', [
/]},
(
'FourKeys',
+ 'FourKeys_to_TwoKeys',
'#dummy',
'SelfRef',
'ArtistUndirectedMap',
'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;
--- /dev/null
+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;
__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;
--
-- 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;
);
--
--- 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 (
);
--
+-- Table: liner_notes
+--
+CREATE TABLE liner_notes (
+ liner_id INTEGER PRIMARY KEY NOT NULL,
+ notes varchar(100) NOT NULL
+);
+
+--
-- Table: artist
--
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 (
);
--
--- 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
);
);
--
+-- 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 (
bar integer NOT NULL,
hello integer NOT NULL,
goodbye integer NOT NULL,
+ sensors character NOT NULL,
PRIMARY KEY (foo, bar, hello, goodbye)
);
);
--
+-- Table: producer
+--
+CREATE TABLE producer (
+ producerid INTEGER PRIMARY KEY NOT NULL,
+ name varchar(100) NOT NULL
+);
+
+--
-- Table: onekey
--
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);