X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSchema%2FLoader.pm;h=8d8d181592ffd7091cca1b1f2ad5b643355ece36;hb=b327622ba07a243c4b5e10b0b7dbd17c20d75b34;hp=0bd0049779899a19286a4d3bc3c8fd81baee8c25;hpb=fc2b71fda3e7cebcb8df6430eb866754bf009350;p=dbsrgits%2FDBIx-Class-Schema-Loader.git diff --git a/lib/DBIx/Class/Schema/Loader.pm b/lib/DBIx/Class/Schema/Loader.pm index 0bd0049..8d8d181 100644 --- a/lib/DBIx/Class/Schema/Loader.pm +++ b/lib/DBIx/Class/Schema/Loader.pm @@ -2,22 +2,19 @@ package DBIx::Class::Schema::Loader; use strict; use warnings; -use base qw/DBIx::Class::Schema/; -use base qw/Class::Data::Accessor/; -use Carp; +use base qw/DBIx::Class::Schema Class::Data::Accessor/; +use Carp::Clan qw/^DBIx::Class/; use UNIVERSAL::require; use Class::C3; -use Data::Dump qw/ dump /; use Scalar::Util qw/ weaken /; # Always remember to do all digits for the version even if they're 0 # i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports # brain damage and presumably various other packaging systems too -our $VERSION = '0.03002'; +our $VERSION = '0.04999_05'; -__PACKAGE__->mk_classaccessor('dump_to_dir'); -__PACKAGE__->mk_classaccessor('loader'); -__PACKAGE__->mk_classaccessor('_loader_args'); +__PACKAGE__->mk_classaccessor('_loader_args' => {}); +__PACKAGE__->mk_classaccessors(qw/dump_to_dir _loader_invoked _loader loader_class/); =head1 NAME @@ -29,7 +26,6 @@ DBIx::Class::Schema::Loader - Dynamic definition of a DBIx::Class::Schema use base qw/DBIx::Class::Schema::Loader/; __PACKAGE__->loader_options( - relationships => 1, constraint => '^foo.*', # debug => 1, ); @@ -46,15 +42,20 @@ DBIx::Class::Schema::Loader - Dynamic definition of a DBIx::Class::Schema DBIx::Class::Schema::Loader automates the definition of a L by scanning database table definitions and -setting up the columns and primary keys. +setting up the columns, primary keys, and relationships. -DBIx::Class::Schema::Loader currently supports DBI for MySQL, -PostgreSQL, SQLite and DB2. +DBIx::Class::Schema::Loader currently supports only the DBI storage type. +It has explicit support for L, L, L, +L, and L. Other DBI drivers may function to +a greater or lesser degree with this loader, depending on how much of the +DBI spec they implement, and how standard their implementation is. + +Patches to make other DBDs work correctly welcome. See L for notes on writing your own vendor-specific subclass for an unsupported DBD driver. -This module requires L 0.06 or later, and obsoletes +This module requires L 0.07006 or later, and obsoletes the older L. This module is designed more to get you up and running quickly against @@ -63,12 +64,21 @@ than to be what you use in the long term for a complex database/project. That being said, transitioning your code from a Schema generated by this module to one that doesn't use this module should be straightforward and -painless (as long as you're not using any methods that are now deprecated -in this document), so don't shy away from it just for fears of the -transition down the road. +painless, so don't shy away from it just for fears of the transition down +the road. =head1 METHODS +=head2 loader_class + +Set the loader class to be instantiated when L is called. +If the classname starts with "::", "DBIx::Class::Schema::Loader" is +prepended. Defaults to L (which must +start with "::" when using L). + +This is mostly useful for subclassing existing loaders or in conjunction +with L. + =head2 loader_options Example in Synopsis above demonstrates a few common arguments. For @@ -76,30 +86,19 @@ detailed information on all of the arguments, most of which are only useful in fairly complex scenarios, see the L documentation. -This method is *required*, for backwards compatibility reasons. If -you do not wish to change any options, just call it with an empty -argument list during schema class initialization. +If you intend to use C, you must call +C before any connection is made, or embed the +C in the connection information itself as shown +below. Setting C after the connection has +already been made is useless. =cut sub loader_options { my $self = shift; - my %args; - if(ref $_[0] eq 'HASH') { - %args = %{$_[0]}; - } - else { - %args = @_; - } - - my $class = ref $self || $self; - $args{schema} = $self; - $args{schema_class} = $class; - weaken($args{schema}) if ref $self; - + my %args = (ref $_[0] eq 'HASH') ? %{$_[0]} : @_; $self->_loader_args(\%args); - $self->_invoke_loader if $self->storage && !$class->loader; $self; } @@ -108,33 +107,61 @@ sub _invoke_loader { my $self = shift; my $class = ref $self || $self; - $self->_loader_args->{dump_directory} ||= $self->dump_to_dir; + my $args = $self->_loader_args; + + # set up the schema/schema_class arguments + $args->{schema} = $self; + $args->{schema_class} = $class; + weaken($args->{schema}) if ref $self; + $args->{dump_directory} ||= $self->dump_to_dir; # XXX this only works for relative storage_type, like ::DBI ... - my $impl = "DBIx::Class::Schema::Loader" . $self->storage_type; + my $impl = $self->loader_class + || "DBIx::Class::Schema::Loader" . $self->storage_type; + $impl = "DBIx::Class::Schema::Loader${impl}" if $impl =~ /^::/; $impl->require or croak qq/Could not load storage_type loader "$impl": / . qq/"$UNIVERSAL::require::ERROR"/; - # XXX in the future when we get rid of ->loader, the next two - # lines can be replaced by "$impl->new(%{$self->_loader_args})->load;" - $class->loader($impl->new(%{$self->_loader_args})); - $class->loader->load; + $self->_loader($impl->new(%$args)); + $self->_loader->load; + $self->_loader_invoked(1); $self; } =head2 connection -See L. +See L for basic usage. + +If the final argument is a hashref, and it contains the keys C +or C, those keys will be deleted, and their values value will be +used for the loader options or class, respectively, just as if set via the +L or L methods above. + +The actual auto-loading operation (the heart of this module) will be invoked +as soon as the connection information is defined. =cut sub connection { - my $self = shift->next::method(@_); + my $self = shift; + + if($_[-1] && ref $_[-1] eq 'HASH') { + for my $option (qw/ loader_class loader_options /) { + if(my $value = delete $_[-1]->{$option}) { + $self->$option($value); + } + } + pop @_ if !keys %{$_[-1]}; + } + + $self = $self->next::method(@_); my $class = ref $self || $self; - $self->_invoke_loader if $self->_loader_args && !$class->loader; + if(!$class->_loader_invoked) { + $self->_invoke_loader + } return $self; } @@ -150,9 +177,10 @@ sub clone { my $clone = $self->next::method(@_); - $clone->_loader_args($self->_loader_args); - $clone->_loader_args->{schema} = $clone; - weaken($clone->_loader_args->{schema}); + if($clone->_loader_args) { + $clone->_loader_args->{schema} = $clone; + weaken($clone->_loader_args->{schema}); + } $clone; } @@ -232,6 +260,8 @@ use this to generate a rough draft manual schema from a dsn without the intermediate step of creating a physical Loader-based schema class. +The return value is the input class name. + This function can be exported/imported by the normal means, as illustrated in these Examples: @@ -240,19 +270,19 @@ illustrated in these Examples: use DBIx::Class::Schema::Loader qw/ make_schema_at /; make_schema_at( 'New::Schema::Name', - { relationships => 1, debug => 1 }, + { debug => 1 }, [ 'dbi:Pg:dbname="foo"','postgres' ], ); # Complex: dump loaded schema to disk, all from the commandline: - perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib -e 'make_schema_at("New::Schema::Name", { relationships => 1 }, [ "dbi:Pg:dbname=foo","postgres" ])' + perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib -e 'make_schema_at("New::Schema::Name", { debug => 1 }, [ "dbi:Pg:dbname=foo","postgres" ])' # Same, but inside a script, and using a different way to specify the # dump directory: use DBIx::Class::Schema::Loader qw/ make_schema_at /; make_schema_at( 'New::Schema::Name', - { relationships => 1, debug => 1, dump_directory => './lib' }, + { debug => 1, dump_directory => './lib' }, [ 'dbi:Pg:dbname="foo"','postgres' ], ); @@ -261,17 +291,27 @@ illustrated in these Examples: sub make_schema_at { my ($target, $opts, $connect_info) = @_; - my $opts_dumped = dump($opts); - my $cinfo_dumped = dump(@$connect_info); - eval qq| - package $target; - use base qw/DBIx::Class::Schema::Loader/; - __PACKAGE__->loader_options($opts_dumped); - __PACKAGE__->connection($cinfo_dumped); - |; - croak "make_schema_at failed: $@" if $@; + { + no strict 'refs'; + @{$target . '::ISA'} = qw/DBIx::Class::Schema::Loader/; + } + + $target->loader_options($opts); + $target->connection(@$connect_info); } +=head2 rescan + +Re-scans the database for newly added tables since the initial +load, and adds them to the schema at runtime, including relationships, +etc. Does not process drops or changes. + +Returns a list of the new monikers added. + +=cut + +sub rescan { my $self = shift; $self->_loader->rescan($self) } + =head1 EXAMPLE Using the example in L as a basis @@ -282,7 +322,6 @@ replace the DB::Main with the following code: use base qw/DBIx::Class::Schema::Loader/; __PACKAGE__->loader_options( - relationships => 1, debug => 1, ); __PACKAGE__->connection('dbi:SQLite:example.db'); @@ -292,86 +331,6 @@ replace the DB::Main with the following code: and remove the Main directory tree (optional). Every thing else should work the same -=head1 DEPRECATED METHODS - -You don't need to read anything in this section unless you're upgrading -code that was written against pre-0.03 versions of this module. This -version is intended to be backwards-compatible with pre-0.03 code, but -will issue warnings about your usage of deprecated features/methods. - -=head2 load_from_connection - -This deprecated method is now roughly an alias for L. - -This method *will* disappear in a future version. - -For now, using this method will invoke the legacy behavior for -backwards compatibility, and merely emit a warning about upgrading -your code. - -It also reverts the default inflection scheme to -use L just like pre-0.03 versions of this -module did. - -You can force these legacy inflections with the -option C, even after switch over -to the preferred L way of doing things. - -See the source of this method for more details. - -=cut - -sub load_from_connection { - my ($self, %args) = @_; - - my $cmds_ver = $Catalyst::Model::DBIC::Schema::VERSION; - if($cmds_ver) { - if($cmds_ver < 0.14) { - warn 'You should upgrade your installation of' - . ' Catalyst::Model::DBIC::Schema to 0.14 or higher, then:'; - } - warn 'You should regenerate your Model files, which may eliminate' - . ' the following deprecation warning:'; - } - warn 'load_from_connection deprecated, please [re-]read the' - . ' [new] DBIx::Class::Schema::Loader documentation'; - - # Support the old connect_info / dsn / etc args... - $args{connect_info} = [ - delete $args{dsn}, - delete $args{user}, - delete $args{password}, - delete $args{options}, - ] if $args{dsn}; - - $self->connection(@{delete $args{connect_info}}) - if $args{connect_info}; - - $self->loader_options('legacy_default_inflections' => 1, %args); -} - -=head2 loader - -This is an accessor in the generated Schema class for accessing -the L -based loader object -that was used during construction. See the -L docs for more information -on the available loader methods there. - -This accessor is deprecated. Do not use it. Anything you can -get from C, you can get via the normal L -methods, and your code will be more robust and forward-thinking -for doing so. - -If you're already using C in your code, make an effort -to get rid of it. If you think you've found a situation where it -is necessary, let me know and we'll see what we can do to remedy -that situation. - -In some future version, this accessor *will* disappear. It was -apparently quite a design/API mistake to ever have exposed it to -user-land in the first place, all things considered. - =head1 KNOWN ISSUES =head2 Multiple Database Schemas @@ -385,8 +344,7 @@ to tables in other schemas will be silently ignored. At some point in the future, an intelligent way around this might be devised, probably by allowing the C option to be an -arrayref of schemas to load, or perhaps even offering schema -constraint/exclusion options just like the table ones. +arrayref of schemas to load. In "normal" L usage, manually-defined source classes and relationships have no problems crossing vendor schemas. @@ -401,9 +359,8 @@ Based upon the work of IKEBE Tomohiro =head1 THANK YOU -Adam Anderson, Andy Grundman, Autrijus Tang, Dan Kubb, David Naughton, -Randal Schwartz, Simon Flack, Matt S Trout, everyone on #dbix-class, and -all the others who've helped. +Matt S Trout, all of the #dbix-class folks, and everyone who's ever sent +in a bug report or suggestion. =head1 LICENSE