lazy_load: sources() returns available source names
Jan Henning Thorsen [Thu, 5 Sep 2013 07:41:43 +0000 (09:41 +0200)]
lib/DBIx/Class/Schema.pm
t/39load_namespaces_lazy.t

index 7bf0687..b59c6f1 100644 (file)
@@ -245,8 +245,12 @@ sub load_namespaces {
   my %resultsets = $class->_map_namespaces(@$resultset_namespace);
 
   if($lazy_load) {
-    # abusing the attribute to store $moniker => [@classnames] information
-    $class->class_mappings->{$_} = [ $results{$_}, $resultsets{$_} || $default_resultset_class ] for keys %results;
+    for(keys %results) {
+      # $source_class => [$source_name, $resultset_class]
+      $class->class_mappings->{$results{$_}} = [ $_, $resultsets{$_} || $default_resultset_class ];
+      # $source_name => [$source_class, $resultset_class]
+      $class->source_registrations->{$_} = [ $results{$_}, $resultsets{$_} || $default_resultset_class ];
+    }
     return;
   }
 
@@ -608,36 +612,28 @@ sub source {
     unless @_;
 
   my $source_name = shift;
-
   my $sreg = $self->source_registrations;
-  return $sreg->{$source_name} if exists $sreg->{$source_name};
 
-  # if we got here, they probably passed a full class name or something to lazy load
-  my $mapped = $self->class_mappings->{$source_name};
+  if(exists $sreg->{$source_name}) {
+    my $source = $sreg->{$source_name};
+    return $self->_lazy_source($source_name, @$source) if ref $source eq 'ARRAY';
+    return $source;
+  }
 
   # if we got here, they probably passed a full class name
-  if(!$mapped) {
-    my $last;
-    for(%{ $self->class_mappings }) {
-      next unless ref $_ and $_->[0] eq $source_name;
-      $mapped = $_;
-      last;
-    }
-  }
-  if(ref $mapped eq 'ARRAY') {
-    my $source_class = $mapped->[0];
-    $self->ensure_class_loaded($source_class);
-    $source_class->resultset_class($mapped->[1]) if $mapped->[1];
-    $self->register_class($source_name, $source_class);
-    $mapped = $source_name;
-    $sreg = $self->source_registrations; # jhthorsen: No idea why data is copied all over the place instead of just changing the ref...
-  }
+  my $mapped = $self->class_mappings->{$source_name};
 
-  if(!$mapped or !exists $sreg->{$mapped}) {
-    $self->throw_exception("Can't find source for ${source_name}");
-  }
+  $self->throw_exception("Can't find source for ${source_name}") unless $mapped;
+  return $self->_lazy_source($mapped->[0], $source_name, $mapped->[1]) if ref $mapped eq 'ARRAY';
+  return $mapped;
+}
+
+sub _lazy_source {
+  my($self, $source_name, $source_class, $resultset_class) = @_;
 
-  return $sreg->{$mapped};
+  $self->ensure_class_loaded($source_class);
+  $source_class->resultset_class($resultset_class) if $resultset_class;
+  $self->source_registrations->{$source_name} = $self->register_class($source_name, $source_class);
 }
 
 =head2 class
index 168ba33..bd2daba 100644 (file)
@@ -5,7 +5,7 @@ use Test::More;
 use lib qw(t/lib);
 use DBICTest; # do not remove even though it is not used
 
-plan tests => 9;
+plan tests => 12;
 
 my $warnings;
 eval {
@@ -14,21 +14,26 @@ eval {
     use base qw/DBIx::Class::Schema/;
     __PACKAGE__->load_namespaces(lazy_load => 1, default_resultset_class => 'RSBase');
 };
-ok !$@ or diag $@;
+ok !$@, 'namespace is loaded' or diag $@;
 ok !$warnings, 'no warnings';
 
-is int DBICNSTest->sources, 0, 'zero sources loaded';
+is_deeply(
+  [ sort DBICNSTest->sources ],
+  [ qw/ A B D R / ],
+ 'sources() available'
+);
 
-my $source_b = DBICNSTest->source('R');
-isa_ok($source_b, 'DBIx::Class::ResultSource::Table');
-my $rset_b   = DBICNSTest->resultset('R');
-isa_ok($rset_b, 'DBICNSTest::RSBase');
-ok ref $source_b->related_source('a'), 'managed to load related';
+for(DBICNSTest->sources) {
+  is ref DBICNSTest->source_registrations->{$_}, 'ARRAY', "$_ is lazy";
+}
+
+my $source_r = DBICNSTest->source('R');
+isa_ok($source_r, 'DBIx::Class::ResultSource::Table');
+my $rset_r   = DBICNSTest->resultset('R');
+isa_ok($rset_r, 'DBICNSTest::RSBase');
+ok ref $source_r->related_source('a'), 'managed to load related';
 
 my $source_a = DBICNSTest->source('A');
 isa_ok($source_a, 'DBIx::Class::ResultSource::Table');
 my $rset_a   = DBICNSTest->resultset('A');
 isa_ok($rset_a, 'DBICNSTest::ResultSet::A');
-
-
-is int DBICNSTest->sources, 3, 'two sources loaded';