release 0.07008
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / RelBuilder.pm
index d78542b..d1e11c3 100644 (file)
@@ -11,10 +11,17 @@ use DBIx::Class::Schema::Loader::Utils 'split_name';
 use File::Slurp 'slurp';
 use Try::Tiny;
 use Class::Unload ();
+use Class::Inspector ();
 use List::MoreUtils 'apply';
 use namespace::clean;
 
-our $VERSION = '0.07002';
+our $VERSION = '0.07008';
+
+# Glossary:
+#
+# remote_relname -- name of relationship from the local table referring to the remote table
+# local_relname  -- name of relationship from the remote table referring to the local table
+# remote_method  -- relationship type from remote table to local table, usually has_many
 
 =head1 NAME
 
@@ -81,6 +88,7 @@ __PACKAGE__->mk_group_accessors('simple', qw/
     inflect_plural
     inflect_singular
     relationship_attrs
+    rel_collision_map
     _temp_classes
 /);
 
@@ -102,6 +110,7 @@ sub new {
         inflect_plural     => $base->inflect_plural,
         inflect_singular   => $base->inflect_singular,
         relationship_attrs => $base->relationship_attrs,
+        rel_collision_map  => $base->rel_collision_map,
         _temp_classes      => [],
     };
 
@@ -280,6 +289,37 @@ sub _remote_relname {
     return $remote_relname;
 }
 
+sub _resolve_relname_collision {
+    my ($self, $moniker, $cols, $relname) = @_;
+
+    return $relname if $relname eq 'id'; # this shouldn't happen, but just in case
+
+    if ($self->base->_is_result_class_method($relname)) {
+        if (my $map = $self->rel_collision_map) {
+            for my $re (keys %$map) {
+                if (my @matches = $relname =~ /$re/) {
+                    return sprintf $map->{$re}, @matches;
+                }
+            }
+        }
+
+        my $new_relname = $relname;
+        while ($self->base->_is_result_class_method($new_relname)) {
+            $new_relname .= '_rel'
+        }
+
+        warn <<"EOF";
+Relationship '$relname' in source '$moniker' for columns '@{[ join ',', @$cols ]}' collides with an inherited method.
+Renaming to '$new_relname'.
+See "RELATIONSHIP NAME COLLISIONS" in perldoc DBIx::Class::Schema::Loader::Base .
+EOF
+
+        return $new_relname;
+    }
+
+    return $relname;
+}
+
 sub generate_code {
     my ($self, $local_moniker, $rels, $uniqs) = @_;
 
@@ -316,6 +356,9 @@ sub generate_code {
         my ( $local_relname, $remote_relname, $remote_method ) =
             $self->_relnames_and_method( $local_moniker, $rel, \%cond,  $uniqs, \%counters );
 
+        $remote_relname = $self->_resolve_relname_collision($local_moniker,  $local_cols,  $remote_relname);
+        $local_relname  = $self->_resolve_relname_collision($remote_moniker, $remote_cols, $local_relname);
+
         push(@{$all_code->{$local_class}},
             { method => 'belongs_to',
               args => [ $remote_relname,
@@ -376,15 +419,15 @@ sub _relnames_and_method {
     if ($counters->{$remote_moniker} > 1) {
         my $relationship_exists = 0;
 
-        if (-f (my $existing_remote_file = $self->{base}->get_dump_filename($remote_class))) {
+        if (-f (my $existing_remote_file = $self->base->get_dump_filename($remote_class))) {
             my $class = "${remote_class}Temporary";
 
-            if (not do { no strict 'refs'; %{$class . '::'} }) {
+            if (not Class::Inspector->loaded($class)) {
                 my $code = slurp $existing_remote_file;
 
                 $code =~ s/(?<=package $remote_class)/Temporary/g;
 
-                $code =~ s/__PACKAGE__->meta->make_immutable;//g;
+                $code =~ s/__PACKAGE__->meta->make_immutable[^;]*;//g;
 
                 eval $code;
                 die $@ if $@;