information_schema as information_schema does not work for readonly
users
- add rel_type param for relationship_attrs coderef
+ - pass link table details to rel_name_map for many_to_many bridges (RT#81091)
0.07033 2012-09-09 16:11:47
- more thoroughly document the new behavior for relationship attributes
remote_class => name of the DBIC class we are related to,
remote_moniker => moniker of the DBIC class we are related to,
remote_columns => columns in the other table in the relationship,
+ # for type => "many_to_many" only:
+ link_class => name of the DBIC class for the link table
+ link_moniker => moniker of the DBIC class for the link table
+ link_rel_name => name of the relationship to the link table
}
DBICSL will try to use the value returned as the relationship name.
my @class2_to_cols = apply { s/^foreign\.//i } keys %{ $rels->[0]{args}[2] };
+ my $link_moniker = $rels->[0]{extra}{local_moniker};
+
my @link_table_cols =
- @{[ $self->schema->source($rels->[0]{extra}{local_moniker})->columns ]};
+ @{[ $self->schema->source($link_moniker)->columns ]};
my @link_table_primary_cols =
- @{[ $self->schema->source($rels->[0]{extra}{local_moniker})->primary_columns ]};
+ @{[ $self->schema->source($link_moniker)->primary_columns ]};
next unless @class1_link_cols + @class2_link_cols == @link_table_cols
&& @link_table_cols == @link_table_primary_cols;
$class2,
$class1_remote_moniker,
\@class1_to_cols,
+ {
+ link_class => $class,
+ link_moniker => $link_moniker,
+ link_rel_name => $class1_to_link_table_rel_name,
+ },
);
$class1_to_class2_relname = $self->_resolve_relname_collision(
$class2,
$class2_remote_moniker,
\@class2_to_cols,
+ {
+ link_class => $class,
+ link_moniker => $link_moniker,
+ link_rel_name => $class2_to_link_table_rel_name,
+ },
);
$class2_to_class1_relname = $self->_resolve_relname_collision(
sub _rel_name_map {
my ($self, $relname, $method, $local_class, $local_moniker, $local_cols,
- $remote_class, $remote_moniker, $remote_cols) = @_;
+ $remote_class, $remote_moniker, $remote_cols, $extra) = @_;
my $info = {
+ %{$extra || {}},
name => $relname,
type => $method,
local_class => $local_class,
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use lib qw(t/lib);
+use make_dbictest_db_multi_m2m;
+use Devel::Dwarn;
+
+use DBIx::Class::Schema::Loader;
+
+my $schema_counter = 0;
+
+{
+ my $hashmap = schema_with(
+ rel_name_map => {
+ foos_2s => "other_foos",
+ bars_2s => "other_bars",
+ },
+ );
+
+ foreach ([qw(Foo bars)], [qw(Bar foos)]) {
+ my ($source, $rel) = @{$_};
+ my $row = $hashmap->resultset($source)->find(1);
+ foreach my $link ("", "other_") {
+ can_ok $row, "${link}${rel}";
+ }
+ }
+}
+{
+ my $submap = schema_with(
+ rel_name_map => sub {
+ my ($args) = @_;
+ if ($args->{type} eq "many_to_many") {
+ like $args->{link_class},
+ qr/\ADBICTest::Schema::${schema_counter}::Result::FooBar(?:One|Two)\z/,
+ "link_class";
+ like $args->{link_moniker}, qr/\AFooBar(?:One|Two)\z/,
+ "link_moniker";
+ like $args->{link_rel_name}, qr/\Afoo_bar_(?:ones|twoes)\z/,
+ "link_rel_name";
+
+ return $args->{name}."_".(split /_/, $args->{link_rel_name})[-1];
+ }
+ },
+ );
+ foreach ([qw(Foo bars)], [qw(Bar foos)]) {
+ my ($source, $rel) = @{$_};
+ my $row = $submap->resultset($source)->find(1);
+ foreach ([ones => 1], [twoes => 2]) {
+ my ($link, $count) = @{$_};
+ my $m2m = "${rel}_${link}";
+ can_ok $row, $m2m;
+ is $row->$m2m->count, $count, "$m2m count";
+ }
+ }
+}
+
+done_testing;
+
+#### generates a new schema with the given opts every time it's called
+sub schema_with {
+ $schema_counter++;
+ DBIx::Class::Schema::Loader::make_schema_at(
+ 'DBICTest::Schema::'.$schema_counter,
+ { naming => 'current', @_ },
+ [ $make_dbictest_db_multi_m2m::dsn ],
+ );
+ "DBICTest::Schema::$schema_counter"->clone;
+}
--- /dev/null
+package make_dbictest_db_multi_m2m;
+
+use strict;
+use warnings;
+use DBI;
+use dbixcsl_test_dir qw/$tdir/;
+
+eval { require DBD::SQLite };
+my $class = $@ ? 'SQLite2' : 'SQLite';
+
+my $fn = "$tdir/dbictest_multi_m2m.db";
+
+unlink($fn);
+our $dsn = "dbi:$class:dbname=$fn";
+my $dbh = DBI->connect($dsn);
+$dbh->do('PRAGMA SYNCHRONOUS = OFF');
+
+$dbh->do($_) for (
+ q|CREATE TABLE foo (
+ foo_id INTEGER PRIMARY KEY
+ )|,
+ q|CREATE TABLE bar (
+ bar_id INTEGER PRIMARY KEY
+ )|,
+ q|CREATE TABLE foo_bar_one (
+ foo_id INTEGER NOT NULL REFERENCES foo(foo_id),
+ bar_id INTEGER NOT NULL REFERENCES bar(bar_id),
+ PRIMARY KEY (foo_id, bar_id)
+ )|,
+ q|CREATE TABLE foo_bar_two (
+ foo_id INTEGER NOT NULL REFERENCES foo(foo_id),
+ bar_id INTEGER NOT NULL REFERENCES bar(bar_id),
+ PRIMARY KEY (foo_id, bar_id)
+ )|,
+ q|INSERT INTO FOO (foo_id) VALUES (1), (2)|,
+ q|INSERT INTO BAR (bar_id) VALUES (1), (2)|,
+ q|INSERT INTO foo_bar_one (foo_id, bar_id) VALUES (1,1),(2,2)|,
+ q|INSERT INTO foo_bar_two (foo_id, bar_id) VALUES (1,1),(1,2),(2,1),(2,2)|,
+);
+
+END { unlink($fn) unless $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP}; }
+
+1;