Subject: | 'form->process' dies when updating has_many relations with Select-fields |
Hello,
I noticed that HFH::Model::DBIC is not able to update has_many relations
when using Select-fields.
The reason is that the data provided by the form is not compatible with
DBIx::Class::ResultSet::RecursiveUpdate., which is used to update the
database.
My first idea was to fix this issue within RecursiveUpdate, but the
patch was not accepted due to several rational reasons.
Take a look at this discussion:
https://rt.cpan.org/Ticket/Display.html?id=65565
I have created a patch which solves this problem for single-keyed
has_many relations.
As far as I can see, multi-keyed has_many-relations are not supported
by HFH-Model-DBIC at all (due to the line
'my ($primary_key) = $source->primary_columns;'
in the "lookup_options" -subroutine. This will not work for multiple
pks, is this right?).
I also attached a testcase fro this bug...
Best regards, Lukas
Subject: | process_hasmany.t |
use strict;
use warnings;
use Test::More tests => 6;
use Test::Exception;
use lib 't/lib';
###########################################################################
{
# Testform for updating has_many relations with Select-fields
package BookDB::Form::User4;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Model::DBIC';
with 'HTML::FormHandler::Render::Simple';
has '+item_class' => ( default => 'User');
has_field 'addresses' => ( type => 'Select', multiple => 1);
# HFH does not now how to fetch the options for 'addresses' from database
# -> providing options
sub options_addresses{
my $self = shift;
my $schema = $self->schema;
my $addr_rs = $schema->resultset('Address');
return [map { {label => $_->country_iso . '/' . $_->city . '/' . $_->street, value => $_->address_id} } $addr_rs->all];
}
no HTML::FormHandler::Moose;
1;
}
###########################################################################
use_ok( 'HTML::FormHandler' );
use_ok( 'BookDB::Schema');
my $schema = BookDB::Schema->connect('dbi:SQLite:t/db/book.db');
ok($schema, 'get db schema');
my $user = $schema->resultset('User')->find('1');
my $form = BookDB::Form::User4->new(item => $user, );
ok( $form, 'form creation' );
my $orig = $form->values;
ok( $orig, 'extracting values' );
lives_ok {$form->process(params => $orig)} 'running form->process with has_many relation' ;
Subject: | hfh_model_dbic_hasmany.patch |
--- lib/HTML/FormHandler/TraitFor/Model/DBIC.pm 2011-03-01 17:46:05.000000000 +0100
+++ lib/HTML/FormHandler/TraitFor/Model/DBIC.pm.patched 2011-03-01 17:46:56.000000000 +0100
@@ -89,6 +89,23 @@
return $self->item;
}
+around values => sub{
+ my $orig = shift;
+ my $self = shift;
+ my $source = $self->source;
+ my $values = $self->$orig;
+ foreach my $key (keys %$values){
+ if( $self->guess_field_type($key) eq 'Multiple'){
+ my $ids = $values->{$key};
+ croak "updates for has_many relations has to be a ARRAYREF" unless ref($ids) eq 'ARRAY';
+ my @primaries = $self->_get_related_source($source, $key)->primary_columns;
+ croak "multi-key has_many relations are not supported" unless @primaries && @primaries == 1;
+ $values->{$key} = [map {ref($_) && ref($_) eq 'HASH' ? $_ : {$primaries[0] => $_}} @$ids];
+ }
+ }
+ return $values;
+};
+
# undocumented because this is going to be replaced
# by a better method
sub guess_field_type