[Catalyst] C::C::FormBuilder - Forwarding to another
action overwrites data from the calling action
Danny Warren
danny at io.com
Wed Feb 14 11:50:54 GMT 2007
Apologies, I should have mentioned that I was using the controller code =
from my first mail. I have attached my test controller as Test.pm.
Thank you for your explanation about how $c->formbuilder works with =
forwards, that makes some of what I am seeing make more sense (and that =
I had some incorrect assumptions about how forwards worked, will brush =
up on the catalyst docs).
I should clarify my question from the previous mail, reading it again it =
wasn't very clear.
Based on the code you provided, I created a new Action::TT that attempts =
to place a copy of the fb objects in a hash so it can be later accessed =
by form name in the template (ex: forms.foo.FormBuilder). My base =
controller is attached as Multiple.pm and my modified Action::TT is =
attached as TT.pm.
The problem is that, even though the C::C::FormBuilder code is called =
twice (once for each action), only the last form to be processed is kept =
in $controller->_formbuilder. Makes sense, given what you explained =
below about forwards, but that still leaves me wondering how to:
a) grab the name of the form so I can put multiple forms in a stash hash =
(since _formbuilder->name is always that of the last form forwarded to)
b) put the correct form data in the stash for each form, since the data =
for the last form processed will always be in _formbuilder.
To see this in action, here is the log snippet from my last e-mail (you =
can see that C::C::FB runs against both actions, foo and foo_search, but =
that foo_search's data is the only thing that ends up in _formbuilder =
for both). See attached TT.pm for how I am grabbing the form data, =
maybe I am doing it wrong...
[debug] Form (foo): Looking for config file foo.fb
[debug] Form (foo): Found form config =
/home/dwarren/MyApp/root/forms/foo.fb
[debug] Form (foo_search): Looking for config file foo_search.fb
[debug] Form (foo_search): Found form config =
/home/dwarren/MyApp/foo_search.fb
[debug] ACTION: foo
[debug] REAL ACTION: foo_search
[debug] FORM NAME: foo_search
[debug] ACTION: foo
[debug] REAL ACTION: foo
[debug] FORM NAME: foo_search
I also ran the same code you provided in your last e-mail, and it =
happens there as well - the data is for the last form that was forwarded =
to. I would expect that C::C::FormBuilder is called as it comes across =
the action (which it is) but it looks like "setup_template_vars" happens =
later, once $_formbuilder has been populated with the forwarded data.
If I am just not grasping something, let me know. Maybe there is =
something funky with my Catalyst environment as well (if your sample =
code works for you and it does not for me)?
Sorry again if this confusing or long-winded. I have just been pulling =
my hair out on this one, and I don't think I know the guts of catalyst =
well enough yet to properly debug and explain what I am seeing.
Thank you again for your time!
Danny
Juan Camacho wrote:
> On 2/12/07, Danny Warren <danny at io.com> wrote:
>> It looks to me that forwarding from one "Form" action to another "Form"
>> action causes the FormBuilder data from the first action to be
>> overwritten.
>>
> =
>> Can you confirm this, or am I doing something wrong here? I am still
>> somewhat green with Catalyst, so I might be misunderstanding exactly how
>> forwards work. From reading the docs, I was under the impression that
>> two actions should not clobber each other upon forwarding (since
>> forwarded actions are processed inside an eval).
>>
> =
> Each action will have it's own formbuilder object instance. After you
> return from the forward to another form action, $self->formbuilder
> will be a brand new FormBuilder object.
> =
> sub foo : Form('foo') {
> my ($self, $c) =3D @_;
> # $self->formbuilder is for foo form
> $self->forward('bar');
> # now $self->formbuilder is for bar form
> }
> =
> sub bar : Form('bar') { ... }
> =
> Consequently, each action should do it's own thing with it's
> FormBuilder object -- e.g. validate, add or change form fields). Not
> sure what kind of problem you are having as a result of this since you
> didn't provide sample Controller code.
> =
> _______________________________________________
> List: Catalyst at lists.rawmode.org
> Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.or=
g/
> Dev site: http://dev.catalyst.perl.org/
> =
-------------- next part --------------
package Catalyst::Controller::FormBuilder::Multiple;
use strict;
use base qw| Catalyst::Controller::FormBuilder |;
sub __setup
{
my $self =3D shift;
my $class =3D ref $self;
=
# Get a copy of the template setting or use default
# NOTE: Duplicated from parent, unsure of best way to do this cleanly
my $config =3D $self->config->{'Controller::FormBuilder'} || {};
my $tmpl_type =3D $config->{template_type} || "TT";
=
# Override the action value from the config to point to our template
# actions, which will be passed on to the parent's setup method
$config->{action} ||=3D "Catalyst::Controller::FormBuilder::Multiple::Act=
ion::$tmpl_type";
=
$self->SUPER::__setup();
}
1;
-------------- next part --------------
package MyApp::Controller::Test;
use strict;
use warnings;
use base 'Catalyst::Controller::FormBuilder::Multiple';
sub foo : Local Form
{
my ( $self, $c ) =3D @_;
my $foo_form =3D $self->formbuilder;
my $foo_search_form =3D $c->forward('foo_search');
}
sub foo_search : Local Form
{
my ( $self, $c ) =3D @_;
my $form =3D $self->formbuilder;
return $form;
}
1;
-------------- next part --------------
package Catalyst::Controller::FormBuilder::Multiple::Action::TT;
use strict;
use base qw| Catalyst::Controller::FormBuilder::Action::TT |;
sub setup_template_vars
{
my $self =3D shift;
my ( $controller, $c ) =3D @_; =
=
$self->SUPER::setup_template_vars(@_); =
=
# Get the name of the current form, and the stash and obj names that have=
already
# been created
my $form_name =3D $controller->_formbuilder->name;
my $stash_name =3D $controller->_fb_setup->{stash_name};
my $obj_name =3D $controller->_fb_setup->{obj_name};
=
# If a form name is defined, create aliases to this form by name
# NOTE: Will make multiple form hash key configurable later
if ( defined $form_name )
{
$c->stash->{forms}{$form_name}{$stash_name} =3D $c->stash->{$stash_name=
};
$c->stash->{forms}{$form_name}{$obj_name} =3D $c->stash->{$obj_name};
}
=
# DEBUG, will remove later
$c->log->debug("REAL ACTION: " . ( $self->_attr_params->[0] || $self->rev=
erse ) );
$c->log->debug("ACTION: " . $c->action );
$c->log->debug("FORM NAME: " . $form_name);
}
1;
More information about the Catalyst
mailing list