[Catalyst] Validating single arg id

Zbigniew Lukasiak zzbbyy at gmail.com
Wed Oct 21 12:11:28 GMT 2009


On Fri, Oct 16, 2009 at 5:24 PM, iain <iainhubbard at googlemail.com> wrote:
> 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).
>>
>
> We did this sort of thing until we started to use chained actions.
> Now we validate once at the start of the chain e.g.
>
> sub start : Chained('/') CaptureArgs(0) {
>   my ( $self, $c ) = @_;
>     # your validation here
>   my $obj = $c->model( 'DB::Foo' )->find( $id )
>      || return $c->res->status( 404 );
>
>   $c->stash->{obj} = $obj;
>
>   return 1;
> }
>
> sub view : Chained('start') Args(0) {
>   my ( $self, $c ) = @_;
>   # do something with $c->stash->{obj}
>   return 1;
> }

What is the advantage of this over:

sub view : Local {
  my ( $self, $c, $id ) = @_;
  $self->start( $c, $id );
  # do something with $c->stash->{obj}
  return 1;
}


-- 
Zbigniew Lukasiak
http://brudnopis.blogspot.com/
http://perlalchemy.blogspot.com/



More information about the Catalyst mailing list