Merge 'trunk' into 'DBIx-Class-resultset'
Matt S Trout [Tue, 20 Dec 2005 01:59:46 +0000 (01:59 +0000)]
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

lib/DBIx/Class/Core.pm
lib/DBIx/Class/Manual/Cookbook.pod
lib/DBIx/Class/PK/Auto.pm
lib/DBIx/Class/PK/Auto/MSSQL.pm
lib/DBIx/Class/PK/Auto/MySQL.pm
lib/DBIx/Class/PK/Auto/Oracle.pm
lib/DBIx/Class/PK/Auto/Pg.pm
lib/DBIx/Class/PK/Auto/SQLite.pm
lib/DBIx/Class/Table.pm
lib/DBIx/Class/Validation.pm [new file with mode: 0644]
t/run/13oracle.tl

index 5db8b01..88d3c4b 100644 (file)
@@ -14,7 +14,8 @@ __PACKAGE__->load_components(qw/
   TableInstance
   ResultSetInstance
   Exception
-  AccessorGroup/);
+  AccessorGroup
+  Validation/);
 
 1;
 
index 48edc40..9bdd280 100644 (file)
@@ -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<new> method. Note the use of C<next::method>.
+
+    sub new {
+        my( $class, $attrs ) = @_; 
+        
+        $attrs->{ foo } = 'bar' unless defined $attrs->{ foo };
+        
+        $class->next::method( $attrs );
+    }
+
 =back
index ce745aa..6b5356a 100644 (file)
@@ -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<PK::Auto::SQLite>, in your
+table classes:
+
+    __PACKAGE__->load_components(qw/PK::Auto::SQLite Core/);
+
+Note that C<PK::Auto::SQLite> 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<PK::Auto> class at runtime.
+
+=head1 LOGIC
+
+C<PK::Auto> does this by letting the database assign the primary key
+field and fetching the assigned value afterwards.
 
 =head1 METHODS
 
index 59877f1..3ae6287 100644 (file)
@@ -20,6 +20,10 @@ DBIx::Class::PK::Auto::MSSQL - Automatic Primary Key class for MSSQL
 \r
 =head1 SYNOPSIS\r
 \r
+    # In your table classes\r
+    __PACKAGE__->load_components(qw/PK::Auto::MSSQL Core/);\r
+    __PACKAGE__->set_primary_key('id');\r
+\r
 =head1 DESCRIPTION\r
 \r
 This class implements autoincrements for MSSQL.\r
@@ -32,4 +36,4 @@ Brian Cassidy <bricas@cpan.org>
 \r
 You may distribute this code under the same terms as Perl itself.\r
 \r
-=cut
\ No newline at end of file
+=cut\r
index 8644120..57b428d 100644 (file)
@@ -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.
index 1186b1a..a9bde71 100644 (file)
@@ -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.
index 78d1d65..611a6e1 100644 (file)
@@ -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.
index 24bb045..8c83cff 100644 (file)
@@ -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.
index d370ce2..01771ee 100644 (file)
@@ -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 (file)
index 0000000..623766c
--- /dev/null
@@ -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 <bluefeet@cpan.org>
+
+=head1 LICENSE
+
+You may distribute this code under the same terms as Perl itself.
+
index a5ab861..d524b96 100644 (file)
@@ -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) {