3
votes

I am using Catalyst Perl MVC framework with HTML::FormHandler as forms processor.

Are there any ways to create multiple objects and save them into appropriate separate tables using single form?

2
I have looked for such general solution for other frameforks and form generators too but have not found any solution for now. - w.k

2 Answers

3
votes

After some time was spent reading the documentation and finally IRC help I figured out how to do it. It's quite simple.

Let's say we have 2 related tables: 'account' and 'user'. And 'account' hasMany 'users', with this relationship being called 'users'.

The code in controller Account.pm stays the same (remember we are using HTML::FormHandler to process the form and create new objects):

sub register : Chained('base') :PathPart('register') :Args(0) {
    my ($self, $c ) = @_;
    my $account = $c->model('DB::Account')->new_result({});
    return $self->form_create($c, $account);
}
sub form_create {
    my ( $self, $c, $account ) = @_;
    my $form = MyApp::Form::Account->new();
    $c->stash( template => 'account/form.tt2', form => $form );
    $form->process( item => $account, params => $c->req->params );
    return unless $form->validated;
}

All we do is use http://metacpan.org/pod/HTML::FormHandler::Field::Repeatable like that in our lib/MyApp/Form/Account.pm:

package MyApp::Form::Account;

use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Model::DBIC';
use namespace::autoclean;

has '+item_class' => ( default => 'Account' );
has_field 'organization';
# other fields ...

# User Part Form
has_field 'users' => ( type => 'Repeatable' ); # 'users' is our relationship name!
has_field 'users.first';
has_field 'users.last';
# and so on...
has_field 'submit' => ( type => 'Submit', value => 'Submit' );
__PACKAGE__->meta->make_immutable;
1;

After submitting we get freshly created 'account' and 'user' objects, where 'user' already has corresponding 'account_id' inserted :)

1
votes
  1. Form submits
  2. Params are validated

    $form->process()

  3. Data is inserted into tables as appropriate.

    $rec = $c->model(table_1)->create(valid_data);
    $rec->create_related('relationship_name', related_data);

I am unaware of a method for having DBIC perform both inserts automatically. But that isn't to say that one doesn't exist. I just didn't see anything in the FormHandler::DBIC documentation.