Doubt it has anything to do with your environment. I thought I had
tested it a while back when helping someone else, but maybe something
was overlooked since I never got a final word back from the guy I was
helping.  I think I have an idea of what might be wrong -- it has to
do with the following sequence of events:

Action foo
========
1) setup new FormBuilder before action
2) Run foo action which then $c->forwards to foo_search
   Action foo_search
  ==============
  1a) setup new FormBuilder before action
  1b) run foo_search action
  1c) setup_template_vars for foo_search after action
3) setup_template_vars for foo after action

Problem in #3 is that $self->_formbuilder is clobbered from the inner
forward action.

I will try to look into this today and get back to you, but it may not
be until quite late tonight and I won't be able to spend too much time
on it until this weekend.  In the mean time, send *me* directly a
zip/gz of a minimal MyApp catalyst application (including forms and tt
files) so I can quickly get going on it.

Hopefully others will chime in to provide other ideas and
clarification of the action sequence.


On 2/14/07, Danny Warren <[EMAIL PROTECTED]> wrote:
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 <[EMAIL PROTECTED]> 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) = @_;
>   # $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: [email protected]
> Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/[email protected]/
> Dev site: http://dev.catalyst.perl.org/
>

package Catalyst::Controller::FormBuilder::Multiple;

use strict;
use base qw| Catalyst::Controller::FormBuilder |;

sub __setup
{
  my $self = shift;
  my $class = 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 = $self->config->{'Controller::FormBuilder'} || {};
  my $tmpl_type = $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} ||= 
"Catalyst::Controller::FormBuilder::Multiple::Action::$tmpl_type";

  $self->SUPER::__setup();
}

1;

package MyApp::Controller::Test;

use strict;
use warnings;
use base 'Catalyst::Controller::FormBuilder::Multiple';

sub foo : Local Form
{
  my ( $self, $c ) = @_;
  my $foo_form = $self->formbuilder;
  my $foo_search_form = $c->forward('foo_search');
}

sub foo_search : Local Form
{
  my ( $self, $c ) = @_;
  my $form = $self->formbuilder;
  return $form;
}

1;
package Catalyst::Controller::FormBuilder::Multiple::Action::TT;

use strict;
use base qw| Catalyst::Controller::FormBuilder::Action::TT |;

sub setup_template_vars
{
  my $self = shift;
  my ( $controller, $c ) = @_;

  $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  = $controller->_formbuilder->name;
  my $stash_name = $controller->_fb_setup->{stash_name};
  my $obj_name   = $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} = $c->stash->{$stash_name};
    $c->stash->{forms}{$form_name}{$obj_name} = $c->stash->{$obj_name};
  }

  # DEBUG, will remove later
  $c->log->debug("REAL ACTION: " . ( $self->_attr_params->[0] || $self->reverse 
) );
  $c->log->debug("ACTION: " . $c->action );
  $c->log->debug("FORM NAME: " . $form_name);
}

1;
_______________________________________________
List: [email protected]
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/[email protected]/
Dev site: http://dev.catalyst.perl.org/



_______________________________________________
List: [email protected]
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/[email protected]/
Dev site: http://dev.catalyst.perl.org/

Reply via email to