[cgiapp] RunmodeDeclare and ValidateRM incompatibility?
Rhesa Rozendaal
perl at rhesa.com
Wed Jun 17 16:12:09 EDT 2009
Richard Jones wrote:
> In the following example code, which uses CAP::RunmodeDeclare for
> runmode handling:
>
> #-----------------------------------------------------------------------
> runmode edit ($id) {
> my $errs = shift;
>
> $id || return $self->error('no id passed to edit'); # warn 'id:'.$id;
>
> my $data = $self->model->get_some_data($id);
>
> [ .. ]
> return $self->tt_process($errs);
> }
>
> #-----------------------------------------------------------------------
> runmode update ($id) {
> # if param 'id' passed, return error to edit():
> my $error_rm = $id ? 'edit' : 'default';
>
> my $dfv = $self->check_rm( $error_rm, '_update_validate_profile' )
> || return $self->dfv_error_page;
>
> [ .. ]
> }
>
> A url of '/myapp/update/1' via CA::Dispatch calls the 'update' runmode,
> which captures the param '1' into the var $id. All works as advertised.
>
> But if validation in update() fails, the 'update' runmode is required to
> return the dfv error page for 'edit', but it doesn't, instead a fatal
> error results from the consequence of edit() capturing the value of dfv
> errors in $id, which then kills the model method as it tries to execute
> an sql statement using the dfv errors hashref instead of an id value.
>
> The problem seems to be that, according to the docs, RunmodeDeclare will
> capture variables passed as $self->baz(1, "me") as well as from the
> query object. So 'edit ($id)' means $id will capture anything passed
> into the rm. What seems odd is that the dfv errors hashref is also
> captured in the first arg shifted from @_:
That's the issue: the arguments aren't shifted off @_, they're assigned from
it. CAP::RD rewrites this:
runmode something ($some, $variables)
into this:
sub something {
my $self = shift;
my ($some, $variables) = @_;
$some = $self->query->param('some') unless defined $some;
$some = $self->param('some') unless defined $some;
...
In other words, it tries treating the signature as a regular method signature
first, and only falls back to looking in $self->query or $self->param if the
variables are still undefined.
And it also explains why you got the errs hashref in both $id and $errs, since
@_ is still unchanged.
> runmode edit ($id) {
> my $errs = shift;
>
> warn Dumper $id; # contains the dfv errors hashref
> warn Dumper $errs; # also contains the dfv errors hashref !!
>
> [ .. ]
> }
>
> Of course it all works fine if I switch back to conventional runmode
> handling, or to AutoRunmode.
The other solution would be to recognise that dfv_error_page passes the dfv
hashref as the first argument, and name that in your signature:
runmode edit ($errs, $id) { ...
That way, $errs is picked up from @_, while $id is picked up from either
$self->query or $self->param (provided dfv_error_page doesn't pass additional
parameters).
HTH,
Rhesa
More information about the cgiapp
mailing list