Skip Menu |

This queue is for tickets about the HTML-FormHandler-Model-DBIC CPAN distribution.

Report information
The Basics
Id: 66294
Status: resolved
Priority: 0/
Queue: HTML-FormHandler-Model-DBIC

People
Owner: Nobody in particular
Requestors: LUKAST [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.14
Fixed in: (no value)



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
Subject: Re: [rt.cpan.org #66294] 'form->process' dies when updating has_many relations with Select-fields
Date: Tue, 01 Mar 2011 14:09:24 -0500
To: bug-HTML-FormHandler-Model-DBIC [...] rt.cpan.org
From: Gerda Shank <gerda.shank [...] gmail.com>
Lukas: I don't think that this form and its relationship to the database is structured properly. The 'Multiple' select field type is used for many_to_many relationships. (The 'single' select is for has_many relationships.) What you're doing here is a mixture of two different types of relationships, and doesn't make a lot of sense to me. I'm guessing that you have a static list of addresses that you want the user to select from. For that case, you would need a different 'address' table that doesn't include the foreign key (user_id) of the user table, plus a user_address mapping table, which contains user_id and address_id columns. You would still have to create the options, unless the address table has a single column that you would want to use as a label. And the name of the field would be the 'many_to_many' relation, not the 'has_many' relation. If what you have is a 'has_many' relationship to a number of addresses that ARE specific to this user, and this form is trying to select particular addresses for some other purpose, you still ought to have a many_to_many relationship in there somewhere, and a 'has_many' relationship to a mapping table. Possibly what you are trying to do has been obscured by using the existing example. If this is the case, I suggest that you provide the pertinent information for the tables and the form, so that I can understand what you're trying to do. Gerda
Hello Gerda, First of all: Thanks for the very quick answer! I think it was a bad Idea to use the existing example to demonstrate my issue. Sorry for the confusion. I have created a very simple example for this bug. I hope this helps to understand my problem. Im am using 'multiple-select' fields for 'has_many' relations, because I think using 'single-select' fields for 'has_many' relations is not usefull at all (at least in my application). Why should I create a "has_many" relation, when it is not possible to select multiple entries? This would be the same as creating a 'has_one' relation. I am using 'has_many' relations because I need to select multiple items! Using 'many_to_many' instead of 'has_many' is not possible for me. And even if it would be possible, it would have some negative side-effects. But take a look at my example. A short description is included at the top of 'hasmany_select.t' Cheers, Lukas
Subject: HFH-hasmany-select-test.tar.bz2
Download HFH-hasmany-select-test.tar.bz2
application/x-bzip2 2.8k

Message body not shown because it is not plain text.

Subject: Re: [rt.cpan.org #66294] 'form->process' dies when updating has_many relations with Select-fields
Date: Fri, 04 Mar 2011 16:31:06 -0500
To: bug-HTML-FormHandler-Model-DBIC [...] rt.cpan.org
From: Gerda Shank <gerda.shank [...] gmail.com>
Lukas: I looked at your example, and the way you're using a select is non-standard and is not supported by the FormHandler select field. I've attached a version of your example with how it would work with a many_to_many. Which doesn't 'take away' a tool from somebody who has selected it. It's currently not possible to automatically do the kind of processing that you want. I suggest that you look in the FormHandler cookbook: http://search.cpan.org/~gshank/HTML-FormHandler-0.33002/lib/HTML/FormHandler/Manual/Cookbook.pod#Example_of_a_form_with_custom_database_interface That example is similar to what you're trying to do. It might be possible to generalize that kind of operation, but it's not a trivial problem, and the work hasn't been done. Gerda
Download with_m2m.tar.gz
application/x-gzip 4.2k

Message body not shown because it is not plain text.

Subject: Re: [rt.cpan.org #66294] 'form->process' dies when updating has_many relations with Select-fields
Date: Fri, 04 Mar 2011 19:34:34 -0500
To: bug-HTML-FormHandler-Model-DBIC [...] rt.cpan.org
From: Gerda Shank <gerda.shank [...] gmail.com>
Lukas: I took another look at your patch and this issue. Fixing the general case is complicated, but your particular case seems doable. I'm not sure that I like putting the around on values in the model though. I think I'd rather do something explicitly in the field. I should have something available in the next couple of days. Gerda
Hi Gerda, I totaly agree that my patch is far from being a perfect solution. It is a quick fix which solved the problem for me, without detailed knowledge of how the fields work. And it does not seem to disturb the original Formhandlers functionality (at least the tests included in the module still look good...). I also prefere the idea to fix the problem where it originated (in the field) and not where it appeared (as the 'around'-solution does). I realy appreciate your work. Let me know if you need any assistance. Thanks a lot, Lukas
Subject: Re: [rt.cpan.org #66294] 'form->process' dies when updating has_many relations with Select-fields
Date: Tue, 08 Mar 2011 09:35:06 -0500
To: bug-HTML-FormHandler-Model-DBIC [...] rt.cpan.org
From: Gerda Shank <gerda.shank [...] gmail.com>
Lukas: There's code in the github repo (for FormHandler, not the DBIC model) right now which you can try. It's not totally satisfactory--this is one of those problems where there is no completely satisfying solution, unfortunately. And the change will handle your specific situation, but not a number of others that I can imagine. You would define your tools field like this: has_field 'tools' => ( type => 'Select', multiple => 1, has_many => 'id' ); ...where the 'has_many' attribute of the field is the primary key name of the related table. The code has been changed to do the equivalent of an inflation of the value from something like [2,3,4] to [{ id => 2}, {id => 3}, {id => 4}]. And deflates it into the fill-in-form value if necessary. I'm curious about the real-world use of this kind of a select. The ToolBox thing shows the issue but doesn't make real sense to me. You have a pool of resources that can be acquired... Then my mind boggles. Gerda
hi Gerda, I just took a look at the code in the github. It seems to address my problem quite well, at least better than my patch. I will take a closer look at it tomorrow morning. You are right, the 'Toolbox' is not my real world example. I constructed it to show what i need. The real example comes from a more complex and quite special software for physical measurements. The real-world example has tons of dependencies and is hardly documented, thats why I decided to create an 'artificial' example which demonstrates my needs. The real-world example is about silicium-structures which consist of several substructures. These parent-structures are created, split and rearanged all the time, resulting in structures without substructures, structures with substructures, substructures without or with parent-structures, but NEVER substructures with more than one parent structure. To make things even more complicated, structures and substructures are defined in a recursive way... I am not happy with this database-model at all, but I am not in the position to change it. I just have to provide the software which operates on this crazy database-structure... I think providing an artificial example was a good Idea :) Tell me if you are still interested in the real-world example. I will send you a copy as soon as the documentation is (almost) finished. thanks again, Lukas
Closing ticket that was handled quite a while back...