Re: Better handling of constraint failures?

[prev] [thread] [next] [Date index for 2004/08/12]

From: Daniel Collis Puro
Subject: Re: Better handling of constraint failures?
Date: 20:42 on 12 Aug 2004
On Thu, 2004-08-12 at 16:04, Clayton L. Scott wrote:
> On Thu, 12 Aug 2004, Daniel Collis Puro wrote:
> 
> > Folks,
> >
> > Here's the solution I came up with: Is this something that can make it
> > into Class::DBI proper?
> 
> [snip]
> 
> This looks interesting but I don't understand it without the docs to go
> with it. can you create an example as a part of the Album/Artist
> schema?
> 
> 
> Clayton


Here you go.  The only change I'm asking to go into Class::DBI is
putting more information into croak() when an exception is thrown
related to constraints.  If you don't override _croak() the only
difference will be that %info gets populated behind your back.

I'm assuming below that Class::DBI includes the changes to
add_constraint that I enumerated in my previous email. 

This is how I would like to use the more informational exceptions, which
will essentially allow a programmer to use CDBI constraint failure as
triggers to redisplay the entry method (HTML in my case) with specific
messages. 


package Music::DBI;
use base 'Class::DBI';  
Music::DBI->connection('dbi:mysql:dbname', 'username', 'password');

################################################################################
#Special, super-duper overridden croak to catch these 
#"special" exceptions.
sub _croak {
    my ($self, $message, %info) = @_;
    Carp::croak(@_) if(not %info);
    if  ($info{exception_type} eq 'constraint_failure') {
	$self->{__constraint_errors}->{$info{column}}=\%info;
    } else {
	Carp::croak(@_);
    }
}
########################################

package Music::Artist;
use base 'Music::DBI';
Music::Artist->table('artist');
Music::Artist->columns(All => qw/artistid name/);
Music::Artist->has_many(cds => 'Music::CD');

package Music::CD;
use base 'Music::DBI';
Music::CD->table('cd');
Music::CD->columns(All => qw/cdid artist title year/);
Music::CD->has_many(tracks => 'Music::Track');
Music::CD->has_a(artist => 'Music::Artist');
Music::CD->has_a(reldate => 'Time::Piece',
		 inflate => sub { Time::Piece->strptime(shift, "%Y-%m-%d") },
		 deflate => 'ymd',
		);
################################################################################
#Contrived. It doesn't matter for this example, really.
Music::CD->add_constraint('valid title',title=>
			  sub{
			      return 1 if (! $_[0]);
			  });
########################################

Music::CD->might_have(liner_notes => LinerNotes => qw/notes/);

package Music::Track;
use base 'Music::DBI';
Music::Track->table('track');
Music::Track->columns(All => qw/trackid cd position title/);

#-- Meanwhile, in a nearby piece of code! --#

my $artist = Music::Artist->create({ artistid => 1, name => 'U2' });

my $cd = $artist->add_to_cds({ 
			      cdid   => 1,
			      title  => 'October',
			      year   => 1980,
			     });

# Oops, got it wrong.
$cd->year(1981);

################################################################################
#Get the hash of errors we created in the overridden _croak().
#If there aren't errors,  update. If there are,
#use the more specific information to redisplay the form
#with more "intelligent" error messages.

#It would be better to get the constraint errors via a method. . .
my $constraint_errors=$cd->{__constraint_errors};

my @columns=$cd->columns();

if (not %$constraint_errors) {
    $cd->update;
} else {
    my @columns=$cd->columns();
    foreach my $column(@columns) {
	if ($constraint_errors->{$column}) {
	    print "$column had an error. Please correct it!\n";
	    #And redisplay HTML form, or set a variable to cause the
            #form to be redisplayed.
	}
    }
}
########################################
# etc.

foreach my $track ($cd->tracks) {
    print $track->position, $track->title
}

$cd->delete;			# also deletes the tracks

my $cd  = Music::CD->retrieve(1);
my @cds = Music::CD->retrieve_all;
my @cds = Music::CD->search(year => 1980);
my @cds = Music::CD->search_like(title => 'October%');


        -- 
        Dan Collis Puro
Chief Engineer
GeekUprising Internet Consultants
http://www.geekuprising.com
dan@xxxxxxxxxxxx.xxx
781-775-3942

Re: Better handling of constraint failures?
Drew Taylor 17:27 on 12 Aug 2004

Re: Better handling of constraint failures?
Clayton L. Scott 19:29 on 12 Aug 2004

Re: Better handling of constraint failures?
Drew Taylor 19:54 on 12 Aug 2004

Re: Better handling of constraint failures?
Clayton L. Scott 19:53 on 12 Aug 2004

Re: Better handling of constraint failures?
Clayton L. Scott 20:01 on 12 Aug 2004

Re: Better handling of constraint failures?
Perrin Harkins 19:51 on 12 Aug 2004

Re: Better handling of constraint failures?
Daniel Collis Puro 20:01 on 12 Aug 2004

Re: Better handling of constraint failures?
Clayton L. Scott 20:04 on 12 Aug 2004

Re: Better handling of constraint failures?
Daniel Collis Puro 20:42 on 12 Aug 2004

Re: Better handling of constraint failures?
Clayton Scott 21:49 on 12 Aug 2004

Re: Better handling of constraint failures?
Tony Bowden 13:52 on 24 Oct 2004

Generated at 11:34 on 01 Dec 2004 by mariachi v0.52