[Catalyst] Validating single arg id

Matt Whipple matt at mattwhipple.com
Fri Oct 16 14:19:39 GMT 2009

Bill Moseley wrote:
> I have a number of methods that start something like this:
> sub view : Local Args(1) {
>     my ( $self, $c, $id ) = @_;
>     my $obj = $c->model( 'DB::Foo' )->find( $id )
>        || return $c->res->status( 404 );
> If $id is not valid then I might, as in that example, return with a 
> 404 status.
> Of course, if $id is suppose to be an integer and a non-integer or an 
> integer out of range is provided then the the database will throw an 
> exception, which I want to prevent.  I want valid ids to return an 
> object and *anything* else to return undef before hitting the database.
> This is pretty low-level validation -- just validating primary key.  
> For more complex validation I use a form validation module.
> Obviously, I could do something like
> return $c->res->status(404) unless $c->model('DB::Foo')->is_valid_id( 
> $id )
> in every method, but that's not very DRY.
> What I've done in the past is override the find() or search() method 
> in my model base class so that whatever $id is passed it is 
> validated.  Specific model classes can override the is_valid_id()  
> method if they use keys that are not a common key format (i.e. 
> different integer range or non-integer key).
> What's you approach to validating that $id in situations like this 
> where there's a single id?
> Do you just let the database throw the exception?  I prefer to return 
> 404s for invalid ids, regardless of their format (and likewise for ids 
> that point to valid object, but are not owned by the current user 
> instead of a 403).
I would probably avoid potentially hitting the database unnecessarily, 
and only use the exception in the case of complicated validation.  In 
the case of simple validation, why not something simple along the lines of:

sub some_action {
    my ($self, $c) = (shift, shift);
    #Get type checking out of the way
    my $id = check_id(shift, $c));
    #Continue on with apparently good data

sub check_id {
    my ($id, $c) = @_;
    $c->res->status(404) if ( !validate_id($id) );
    return $id;

sub validate_id {
    return 1 if looks_like_number(shift);
> -- 
> Bill Moseley
> moseley at hank.org <mailto:moseley at hank.org>
> ------------------------------------------------------------------------
> _______________________________________________
> List: Catalyst at lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/

More information about the Catalyst mailing list