From: Matt S Trout Date: Tue, 20 Dec 2005 01:59:46 +0000 (+0000) Subject: Merge 'trunk' into 'DBIx-Class-resultset' X-Git-Tag: v0.05005~119^2~22 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=fa58d4bbe57c3324316e08b5c8e5c6be6899c75e;hp=cda04c3afd46989e1964a6c8a277fd7faa11b291;p=dbsrgits%2FDBIx-Class.git Merge 'trunk' into 'DBIx-Class-resultset' r4570@obrien (orig r392): castaway | 2005-12-14 14:22:23 +0000 Patches from Andreas Hartmeier applied to PK::Auto r4601@obrien (orig r396): marcus | 2005-12-15 15:59:43 +0000 make more sane error message for missing table. r4632@obrien (orig r397): bluefeet | 2005-12-15 17:07:45 +0000 Adding first version of DBIx::Class::Validation. r4633@obrien (orig r398): ningu | 2005-12-15 22:59:01 +0000 - PK::Auto doc patch from dwc r4641@obrien (orig r400): dwc | 2005-12-18 17:59:04 +0000 Update examples to be more explicit about load_components order r4642@obrien (orig r401): bricas | 2005-12-19 20:19:14 +0000 added cookbook example: setting default values --- diff --git a/lib/DBIx/Class/Core.pm b/lib/DBIx/Class/Core.pm index 5db8b01..88d3c4b 100644 --- a/lib/DBIx/Class/Core.pm +++ b/lib/DBIx/Class/Core.pm @@ -14,7 +14,8 @@ __PACKAGE__->load_components(qw/ TableInstance ResultSetInstance Exception - AccessorGroup/); + AccessorGroup + Validation/); 1; diff --git a/lib/DBIx/Class/Manual/Cookbook.pod b/lib/DBIx/Class/Manual/Cookbook.pod index 48edc40..9bdd280 100644 --- a/lib/DBIx/Class/Manual/Cookbook.pod +++ b/lib/DBIx/Class/Manual/Cookbook.pod @@ -110,4 +110,16 @@ illustrate: # book2author table equals the bookID of the books (using the bookID # relationship table +=head2 Setting default values + +It's as simple as overriding the C method. Note the use of C. + + sub new { + my( $class, $attrs ) = @_; + + $attrs->{ foo } = 'bar' unless defined $attrs->{ foo }; + + $class->next::method( $attrs ); + } + =back diff --git a/lib/DBIx/Class/PK/Auto.pm b/lib/DBIx/Class/PK/Auto.pm index ce745aa..6b5356a 100644 --- a/lib/DBIx/Class/PK/Auto.pm +++ b/lib/DBIx/Class/PK/Auto.pm @@ -11,13 +11,36 @@ DBIx::Class::PK::Auto - Automatic Primary Key class =head1 SYNOPSIS + # In your table classes (replace PK::Auto::SQLite with your + # database) + __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/); + __PACKAGE__->set_primary_key('id'); + =head1 DESCRIPTION This class overrides the insert method to get automatically incremented primary keys. -You don't want to be using this directly - instead load the appropriate -one for your database, e.g. PK::Auto::SQLite +You don't want to be using this directly - instead load the +appropriate one for your database, e.g. C, in your +table classes: + + __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/); + +Note that C is specified as the leftmost argument. + +Alternatively, you can load the components separately: + + __PACKAGE__->load_components(qw/Core/); + __PACKAGE__->load_components(qw/PK::Auto::SQLite/); + +This can be used, for example, if you have different databases and +need to determine the appropriate C class at runtime. + +=head1 LOGIC + +C does this by letting the database assign the primary key +field and fetching the assigned value afterwards. =head1 METHODS diff --git a/lib/DBIx/Class/PK/Auto/MSSQL.pm b/lib/DBIx/Class/PK/Auto/MSSQL.pm index 59877f1..3ae6287 100644 --- a/lib/DBIx/Class/PK/Auto/MSSQL.pm +++ b/lib/DBIx/Class/PK/Auto/MSSQL.pm @@ -20,6 +20,10 @@ DBIx::Class::PK::Auto::MSSQL - Automatic Primary Key class for MSSQL =head1 SYNOPSIS + # In your table classes + __PACKAGE__->load_components(qw/PK::Auto::MSSQL Core/); + __PACKAGE__->set_primary_key('id'); + =head1 DESCRIPTION This class implements autoincrements for MSSQL. @@ -32,4 +36,4 @@ Brian Cassidy You may distribute this code under the same terms as Perl itself. -=cut \ No newline at end of file +=cut diff --git a/lib/DBIx/Class/PK/Auto/MySQL.pm b/lib/DBIx/Class/PK/Auto/MySQL.pm index 8644120..57b428d 100644 --- a/lib/DBIx/Class/PK/Auto/MySQL.pm +++ b/lib/DBIx/Class/PK/Auto/MySQL.pm @@ -19,6 +19,10 @@ DBIx::Class::PK::Auto::MySQL - Automatic Primary Key class for MySQL =head1 SYNOPSIS + # In your table classes + __PACKAGE__->load_components(qw/PK::Auto::MySQL Core/); + __PACKAGE__->set_primary_key('id'); + =head1 DESCRIPTION This class implements autoincrements for MySQL. diff --git a/lib/DBIx/Class/PK/Auto/Oracle.pm b/lib/DBIx/Class/PK/Auto/Oracle.pm index 1186b1a..a9bde71 100644 --- a/lib/DBIx/Class/PK/Auto/Oracle.pm +++ b/lib/DBIx/Class/PK/Auto/Oracle.pm @@ -10,7 +10,7 @@ __PACKAGE__->load_components(qw/PK::Auto/); sub last_insert_id { my $self = shift; $self->get_autoinc_seq unless $self->{_autoinc_seq}; - my $sql = "SELECT " . $self->{_autoinc_seq} . ".nextval FROM DUAL"; + my $sql = "SELECT " . $self->{_autoinc_seq} . ".currval FROM DUAL"; my ($id) = $self->storage->dbh->selectrow_array($sql); return $id; } @@ -53,6 +53,10 @@ DBIx::Class::PK::Auto::Oracle - Automatic Primary Key class for Oracle =head1 SYNOPSIS + # In your table classes + __PACKAGE__->load_components(qw/PK::Auto::Oracle Core/); + __PACKAGE__->set_primary_key('id'); + =head1 DESCRIPTION This class implements autoincrements for Oracle. diff --git a/lib/DBIx/Class/PK/Auto/Pg.pm b/lib/DBIx/Class/PK/Auto/Pg.pm index 78d1d65..611a6e1 100644 --- a/lib/DBIx/Class/PK/Auto/Pg.pm +++ b/lib/DBIx/Class/PK/Auto/Pg.pm @@ -43,6 +43,10 @@ DBIx::Class::PK::Auto::Pg - Automatic Primary Key class for Postgresql =head1 SYNOPSIS + # In your table classes + __PACKAGE__->load_components(qw/PK::Auto::Pg Core/); + __PACKAGE__->set_primary_key('id'); + =head1 DESCRIPTION This class implements autoincrements for Postgresql. diff --git a/lib/DBIx/Class/PK/Auto/SQLite.pm b/lib/DBIx/Class/PK/Auto/SQLite.pm index 24bb045..8c83cff 100644 --- a/lib/DBIx/Class/PK/Auto/SQLite.pm +++ b/lib/DBIx/Class/PK/Auto/SQLite.pm @@ -19,6 +19,10 @@ DBIx::Class::PK::Auto::SQLite - Automatic Primary Key class for SQLite =head1 SYNOPSIS + # In your table classes + __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/); + __PACKAGE__->set_primary_key('id'); + =head1 DESCRIPTION This class implements autoincrements for SQLite. diff --git a/lib/DBIx/Class/Table.pm b/lib/DBIx/Class/Table.pm index d370ce2..01771ee 100644 --- a/lib/DBIx/Class/Table.pm +++ b/lib/DBIx/Class/Table.pm @@ -5,6 +5,8 @@ use warnings; use DBIx::Class::ResultSet; +use Carp qw/croak/; + use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/AccessorGroup/); @@ -89,7 +91,7 @@ Returns the column metadata hashref for a column. sub column_info { my ($self, $column) = @_; - die "No such column $column" unless exists $self->_columns->{$column}; + croak "No such column $column" unless exists $self->_columns->{$column}; return $self->_columns->{$column}; } @@ -100,7 +102,7 @@ sub column_info { =cut sub columns { - die "columns() is a read-only accessor, did you mean add_columns()?" if (@_ > 1); + croak "columns() is a read-only accessor, did you mean add_columns()?" if (@_ > 1); return keys %{shift->_columns}; } diff --git a/lib/DBIx/Class/Validation.pm b/lib/DBIx/Class/Validation.pm new file mode 100644 index 0000000..623766c --- /dev/null +++ b/lib/DBIx/Class/Validation.pm @@ -0,0 +1,151 @@ +package DBIx::Class::Validation; + +use strict; +use warnings; + +use base qw( DBIx::Class ); +use Carp qw( croak ); +use English qw( -no_match_vars ); + +local $^W = 0; # Silence C:D:I redefined sub errors. + +our $VERSION = '0.01'; + +__PACKAGE__->mk_classdata( 'validation_module' => 'FormValidator::Simple' ); +__PACKAGE__->mk_classdata( 'validation_profile' ); +__PACKAGE__->mk_classdata( 'validation_auto' => 1 ); + +sub validation_module { + my $class = shift; + my $module = shift; + + eval("use $module"); + croak("Unable to load the validation module '$module' because $EVAL_ERROR") if ($EVAL_ERROR); + croak("The '$module' module does not support the check method") if (!$module->can('check')); + + $class->_validation_module_accessor( $module ); +} + +sub validation { + my $class = shift; + my %args = @_; + + $class->validation_module( $args{module} ) if (exists $args{module}); + $class->validation_profile( $args{profile} ) if (exists $args{profile}); + $class->validatio_auto( $args{auto} ) if (exists $args{auto}); +} + +sub validate { + my $self = shift; + my %data = $self->get_columns(); + my $module = $self->validation_module(); + my $profile = $self->validation_profile(); + my $result = $module->check( \%data => $profile ); + return $result if ($result->success()); + croak( $result ); +} + +sub insert { + my $self = shift; + $self->validate if ($self->validation_auto()); + $self->next::method(@_); +} + +sub update { + my $self = shift; + $self->validate if ($self->validation_auto()); + $self->next::method(@_); +} + +1; +__END__ + +=head1 NAME + +DBIx::Class::Validation - Validate all data before submitting to your database. + +=head1 SYNOPSIS + +In your base DBIC package: + + __PACKAGE__->load_components(qw/... Validation/); + +And in your subclasses: + + __PACKAGE__->validation( + module => 'FormValidator::Simple', + profile => { ... }, + auto => 1, + ); + +And then somewhere else: + + eval{ $obj->validate() }; + if( my $results = $EVAL_ERROR ){ + ... + } + +=head1 METHODS + +=head2 validation + + __PACKAGE__->validation( + module => 'FormValidator::Simple', + profile => { ... }, + auto => 1, + ); + +Calls validation_module(), validation_profile(), and validation_auto() if the corresponding +argument is defined. + +=head2 validation_module + + __PACKAGE__->validation_module('Data::FormValidator'); + +Sets the validation module to use. Any module that supports a check() method just like +Data::FormValidator's can be used here, such as FormValidator::Simple. + +Defaults to FormValidator::Simple. + +=head2 validation_profile + + __PACKAGE__->validation_profile( + { ... } + ); + +Sets the profile that will be passed to the validation module. + +=head2 validation_auto + + __PACKAGE__->validation_auto( 1 ); + +This flag, when enabled, causes any updates or inserts of the class +to call validate() before actually executing. + +=head2 validate + + $obj->validate(); + +Validates all the data in the object against the pre-defined validation +module and profile. If there is a problem then a hard error will be +thrown. If you put the validation in an eval you can capture whatever +the module's check() method returned. + +=head2 auto_validate + + __PACKAGE__->auto_validate( 0 ); + +Turns on and off auto-validation. This feature makes all UPDATEs and +INSERTs call the validate() method before doing anything. The default +is for auto-validation to be on. + +Defaults to on. + +=head1 AUTHOR + +Aran C. Deltac + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. + diff --git a/t/run/13oracle.tl b/t/run/13oracle.tl index a5ab861..d524b96 100644 --- a/t/run/13oracle.tl +++ b/t/run/13oracle.tl @@ -36,7 +36,7 @@ OraTest::Artist->load_components('PK::Auto::Oracle'); # test primary key handling my $new = OraTest::Artist->create({ name => 'foo' }); -ok($new->artistid, "Oracle Auto-PK worked"); +is($new->artistid, 1, "Oracle Auto-PK worked"); # test LIMIT support for (1..6) {