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/;
=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</register_source> 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 }) };
$source->schema($self);
+ return if ($params->{extra});
+
weaken($source->{schema}) if ref($self);
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);
}
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);
no strict 'refs';
no warnings 'redefine';
foreach my $meth (qw/class source resultset/) {
- *{"${target}::${meth}"} =
- sub { shift->schema->$meth(@_) };
+ my $name = join '::', $target, $meth;
+ *$name = Sub::Name::subname $name, sub { shift->schema->$meth(@_) };
}
}
return $schema;
=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
dealing with MSSQL via L<DBD::Sybase>, 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<DBIx::Class::Storage::DBI::Replicated> for an example of this.
+
=head2 connection
=over 4
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
$self->storage->txn_do(@_);
}
-=head2 txn_scope_guard
+=head2 txn_scope_guard (EXPERIMENTAL)
-Runs C<txn_scope_guard> on the schema's storage.
+Runs C<txn_scope_guard> on the schema's storage. See
+L<DBIx::Class::Storage/txn_scope_guard>.
=cut
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;