X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSchema.pm;h=3e9d93e7b683a1a961e0fba934f73efbb2999ef4;hb=5b0b4df82267d761f34c606a1f97b6950a2eed4a;hp=7a358bdf8b41bf9f01392b19cf6ae51bebf14140;hpb=e63a82f7221c61ea4f48403d33196f9f3eb746f0;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index 7a358bd..3e9d93e 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -7,6 +7,7 @@ use DBIx::Class::Exception; use Carp::Clan qw/^DBIx::Class/; use Scalar::Util qw/weaken/; use File::Spec; +use Sub::Name (); require Module::Find; use base qw/DBIx::Class/; @@ -96,7 +97,32 @@ moniker. =cut sub register_source { - my ($self, $moniker, $source) = @_; + my $self = shift; + + $self->_register_source(@_); +} + +=head2 register_extra_source + +=over 4 + +=item Arguments: $moniker, $result_source + +=back + +As L but should be used if the result class already +has a source and you want to register an extra one. + +=cut + +sub register_extra_source { + my $self = shift; + + $self->_register_source(@_, { extra => 1 }); +} + +sub _register_source { + my ($self, $moniker, $source, $params) = @_; %$source = %{ $source->new( { %$source, source_name => $moniker }) }; @@ -105,10 +131,14 @@ sub register_source { $self->source_registrations(\%reg); $source->schema($self); - weaken($source->{schema}) if ref($self); + return if ($params->{extra}); + if ($source->result_class) { my %map = %{$self->class_mappings}; + if (exists $map{$source->result_class}) { + warn $source->result_class . ' already has a source, use register_extra_source for additional sources'; + } $map{$source->result_class} = $moniker; $self->class_mappings(\%map); } @@ -535,7 +565,8 @@ more information. my $schema = $self->compose_namespace($target, $base); { no strict 'refs'; - *{"${target}::schema"} = sub { $schema }; + my $name = join '::', $target, 'schema'; + *$name = Sub::Name::subname $name, sub { $schema }; } $schema->connection(@info); @@ -584,12 +615,31 @@ will produce the output =cut +# this might be oversimplified +# sub compose_namespace { +# my ($self, $target, $base) = @_; + +# my $schema = $self->clone; +# foreach my $moniker ($schema->sources) { +# my $source = $schema->source($moniker); +# my $target_class = "${target}::${moniker}"; +# $self->inject_base( +# $target_class => $source->result_class, ($base ? $base : ()) +# ); +# $source->result_class($target_class); +# $target_class->result_source_instance($source) +# if $target_class->can('result_source_instance'); +# $schema->register_source($moniker, $source); +# } +# return $schema; +# } + sub compose_namespace { my ($self, $target, $base) = @_; my $schema = $self->clone; { no warnings qw/redefine/; - local *Class::C3::reinitialize = sub { }; +# local *Class::C3::reinitialize = sub { }; foreach my $moniker ($schema->sources) { my $source = $schema->source($moniker); my $target_class = "${target}::${moniker}"; @@ -599,9 +649,10 @@ sub compose_namespace { $source->result_class($target_class); $target_class->result_source_instance($source) if $target_class->can('result_source_instance'); + $schema->register_source($moniker, $source); } } - Class::C3->reinitialize(); +# Class::C3->reinitialize(); { no strict 'refs'; no warnings 'redefine'; @@ -624,9 +675,9 @@ sub setup_connection_class { =over 4 -=item Arguments: $storage_type +=item Arguments: $storage_type|{$storage_type, \%args} -=item Return Value: $storage_type +=item Return Value: $storage_type|{$storage_type, \%args} =back @@ -640,6 +691,13 @@ in cases where the appropriate subclass is not autodetected, such as when dealing with MSSQL via L, in which case you'd set it to C<::DBI::Sybase::MSSQL>. +If your storage type requires instantiation arguments, those are defined as a +second argument in the form of a hashref and the entire value needs to be +wrapped into an arrayref or a hashref. We support both types of refs here in +order to play nice with your Config::[class] or your choice. + +See L for an example of this. + =head2 connection =over 4 @@ -662,19 +720,33 @@ or L in general. sub connection { my ($self, @info) = @_; return $self if !@info && $self->storage; - my $storage_class = $self->storage_type; + + my ($storage_class, $args) = ref $self->storage_type ? + ($self->_normalize_storage_type($self->storage_type),{}) : ($self->storage_type, {}); + $storage_class = 'DBIx::Class::Storage'.$storage_class if $storage_class =~ m/^::/; eval "require ${storage_class};"; $self->throw_exception( "No arguments to load_classes and couldn't load ${storage_class} ($@)" ) if $@; - my $storage = $storage_class->new($self); + my $storage = $storage_class->new($self=>$args); $storage->connect_info(\@info); $self->storage($storage); return $self; } +sub _normalize_storage_type { + my ($self, $storage_type) = @_; + if(ref $storage_type eq 'ARRAY') { + return @$storage_type; + } elsif(ref $storage_type eq 'HASH') { + return %$storage_type; + } else { + $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type); + } +} + =head2 connect =over 4 @@ -721,9 +793,10 @@ sub txn_do { $self->storage->txn_do(@_); } -=head2 txn_scope_guard +=head2 txn_scope_guard (EXPERIMENTAL) -Runs C on the schema's storage. +Runs C on the schema's storage. See +L. =cut @@ -856,10 +929,14 @@ sub clone { my $clone = { (ref $self ? %$self : ()) }; bless $clone, (ref $self || $self); + $clone->class_mappings({ %{$clone->class_mappings} }); + $clone->source_registrations({ %{$clone->source_registrations} }); foreach my $moniker ($self->sources) { my $source = $self->source($moniker); my $new = $source->new($source); - $clone->register_source($moniker => $new); + # we use extra here as we want to leave the class_mappings as they are + # but overwrite the source_registrations entry with the new source + $clone->register_extra_source($moniker => $new); } $clone->storage->set_schema($clone) if $clone->storage; return $clone;