From: Brandon L. Black Date: Mon, 31 Jul 2006 06:22:26 +0000 (+0000) Subject: load_namespaces arrayref support X-Git-Tag: v0.08010~43^2~22^2~3 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=f017c022afdd0b519a1be5eb749de6a1180c015f;p=dbsrgits%2FDBIx-Class.git load_namespaces arrayref support --- diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index 8eeaed8..275a0e0 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -300,11 +300,14 @@ source-definition classes that have no manually-created corresponding ResultSet class will have their C set to C. +C takes care of calling C and/or +C for you where neccessary if you didn't do it for yourself. + All of the namespace and classname options to this method are relative to the schema classname by default. To specify a fully-qualified name, prefix it with a literal C<+>. -Example: +Examples: # load My::Schema::Source::CD, My::Schema::Source::Artist, # My::Schema::ResultSet::CD, etc... @@ -325,13 +328,47 @@ Example: My::Schema->load_namespaces( source_namespace => '+Some::Place::Sources', resultset_namespace => '+Another::Place::RSets', - result_namespace => '+Crazy::Stuff::Results', - default_resultset_class => '+You::Never::Know::RSetBase', ); +If you'd like to use multiple namespaces of each type, simply use an arrayref +of namespaces for that option. In the case that the same source-definition +(or resultset, or result) class exists in multiple namespaces, the latter +entries in your list of namespaces will override earlier ones. + + My::Schema->load_namespaces( + source_namespace => [ 'Sources_C', 'Sources_B', 'Sources_A' ], + resultset_namespace => [ '+Some::Place::RSets', 'RSets' ], + ); =cut +# Pre-pends our classname to the given relative classname or +# class namespace, unless there is a '+' prefix, which will +# be stripped. Modifies its argument! +sub _expand_relative_name { + my $class = shift; + return if !$_[0]; + $_[0] = $class . '::' . $_[0] if ! ($_[0] =~ s/^\+//); +} + +# returns a hash of $shortname => $fullname for every package +# found in the given namespaces ($shortname is with the $fullname's +# namespace stripped off) +sub _map_namespaces { + my ($class, @namespaces) = @_; + + my @results_hash; + foreach my $namespace (@namespaces) { + push( + @results_hash, + map { (substr($_, length "${namespace}::"), $_) } + Module::Find::findallmod($namespace) + ); + } + + @results_hash; +} + sub load_namespaces { my ($class, %args) = @_; @@ -344,20 +381,21 @@ sub load_namespaces { . join(q{,}, map { qq{'$_'} } keys %args)) if scalar keys %args; - foreach ($source_namespace, $resultset_namespace, - $result_namespace, $default_resultset_class) { - next if !$_; - $_ = $class . '::' . $_ if !s/^\+//; - } + $class->_expand_relative_name($default_resultset_class); + + for my $arg ($source_namespace, $resultset_namespace, $result_namespace) { + $arg = [ $arg ] if !ref($arg) && $arg; - my %sources = map { (substr($_, length "${source_namespace}::"), $_) } - Module::Find::findallmod($source_namespace); + $class->throw_exception('load_namespaces: namespace arguments must be ' + . 'a simple string or an arrayref') + if ref($arg) ne 'ARRAY'; - my %resultsets = map { (substr($_, length "${resultset_namespace}::"), $_) } - Module::Find::findallmod($resultset_namespace); + $class->_expand_relative_name($_) for (@$arg); + } - my %results = map { (substr($_, length "${result_namespace}::"), $_) } - Module::Find::findallmod($result_namespace); + my %sources = $class->_map_namespaces(@$source_namespace); + my %resultsets = $class->_map_namespaces(@$resultset_namespace); + my %results = $class->_map_namespaces(@$result_namespace); my @to_register; { @@ -373,7 +411,7 @@ sub load_namespaces { my $rs_class = delete $resultsets{$source}; my $rs_set = $source_class->resultset_class; if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') { - if($rs_class) { + if($rs_class && $rs_class ne $rs_set) { warn "We found ResultSet class '$rs_class' for '$source', but it seems " . "that you had already set '$source' to use '$rs_set' instead"; } @@ -390,7 +428,7 @@ sub load_namespaces { $class->ensure_class_loaded($r_class); $source_class->result_class($r_class); } - else { + elsif($r_set ne $r_class) { warn "We found Result class '$r_class' for '$source', but it seems " . "that you had already set '$source' to use '$r_set' instead"; } diff --git a/t/39load_namespaces_3.t b/t/39load_namespaces_3.t index 531aa89..b066d64 100644 --- a/t/39load_namespaces_3.t +++ b/t/39load_namespaces_3.t @@ -6,7 +6,7 @@ use Test::More; unshift(@INC, './t/lib'); -plan tests => 9; +plan tests => 10; my $warnings; eval { @@ -14,7 +14,7 @@ eval { package DBICNSTestOther; use base qw/DBIx::Class::Schema/; __PACKAGE__->load_namespaces( - source_namespace => '+DBICNSTest::Src', + source_namespace => [ '+DBICNSTest::Src', '+DBICNSTest::OtherSrc' ], resultset_namespace => '+DBICNSTest::RSet', result_namespace => '+DBICNSTest::Res' ); @@ -36,3 +36,6 @@ my $rset_b = DBICNSTestOther->resultset('B'); isa_ok($rset_b, 'DBIx::Class::ResultSet'); my $resclass_b = DBICNSTestOther->resultset('B')->result_class; is($resclass_b, 'DBICNSTest::Src::B'); + +my $source_d = DBICNSTestOther->source('D'); +isa_ok($source_d, 'DBIx::Class::ResultSource::Table'); diff --git a/t/lib/DBICNSTest/OtherSrc/D.pm b/t/lib/DBICNSTest/OtherSrc/D.pm new file mode 100644 index 0000000..c3d2a95 --- /dev/null +++ b/t/lib/DBICNSTest/OtherSrc/D.pm @@ -0,0 +1,6 @@ +package DBICNSTest::OtherSrc::D; +use base qw/DBIx::Class/; +__PACKAGE__->load_components(qw/PK::Auto Core/); +__PACKAGE__->table('d'); +__PACKAGE__->add_columns('d'); +1;