Index: /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/has_one_select.yml
===================================================================
--- /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/has_one_select.yml (revision 0)
+++ /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/has_one_select.yml (revision 0)
@@ -0,0 +1,17 @@
+---
+auto_fieldset: 1
+
+elements:
+ - type: Hidden
+ name: id
+
+ - type: Text
+ name: text_col
+
+ - type: Select
+ name: user
+ model_config:
+ resultset: User
+
+ - type: Submit
+ name: submit
Index: /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/has_one.t
===================================================================
--- /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/has_one.t (revision 1485)
+++ /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/update/has_one.t (working copy)
@@ -1,6 +1,6 @@
use strict;
use warnings;
-use Test::More tests => 4;
+use Test::More tests => 9;
use HTML::FormFu;
use lib 't/lib';
@@ -64,3 +64,51 @@
is( $user->name, 'bar' );
}
+$form = HTML::FormFu->new;
+
+$form->load_config_file('t/update/has_one_select.yml');
+
+$form->stash->{schema} = $schema;
+
+{
+ $form->process( {
+ "id" => 3,
+ "text_col" => 'a',
+ "user" => 1,
+ } );
+
+ ok( $form->submitted_and_valid );
+
+ my $row = $schema->resultset('Master')->find(3);
+
+ $form->model->update($row);
+
+ is($row->user->id, 1);
+
+ $form->process( {
+ "id" => 3,
+ "text_col" => 'a',
+ "user" => 99,
+ } );
+
+ ok( $form->submitted_and_valid );
+
+ my $row = $schema->resultset('Master')->find(3);
+
+ $form->model->update($row);
+
+ is($row->user->id, 1);
+
+ $form = HTML::FormFu->new;
+
+ $form->stash->{schema} = $schema;
+
+ $form->load_config_file('t/update/has_one_select.yml');
+
+ $form->model->default_values($row);
+
+ $form->process;
+
+ like($form, qr/value="1" selected=/);
+}
+
Index: /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/lib/DBICTestLib.pm
===================================================================
--- /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/lib/DBICTestLib.pm (revision 1485)
+++ /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/t/lib/DBICTestLib.pm (working copy)
@@ -75,7 +75,7 @@
$dbh->do( <add_columns(
id => { data_type => "INTEGER", is_nullable => 0 },
- master => { data_type => "INTEGER", is_nullable => 0 },
+ master => { data_type => "INTEGER", is_nullable => 1 },
name => { data_type => "TEXT", is_nullable => 0 },
title => { data_type => "TEXT" },
);
Index: /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/lib/HTML/FormFu/Model/DBIC.pm
===================================================================
--- /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/lib/HTML/FormFu/Model/DBIC.pm (revision 1485)
+++ /Users/mo/Documents/workspace/HTML-FormFu-Model-DBIC/lib/HTML/FormFu/Model/DBIC.pm (working copy)
@@ -217,10 +217,13 @@
if ( !defined $info or $info->{attrs}{accessor} eq 'multi' ) {
my @defaults = $dbic->$name->get_column($col)->all;
$field->default( \@defaults );
+ } else {
+ # has_one/might_have
+ my($pk) = $dbic->result_source->primary_columns;
+ $field->default( $dbic->$name->$pk );
}
}
else {
-
# This field is a method expected to return the value
$field->default( $dbic->$name );
}
@@ -442,14 +445,13 @@
return if $attrs->{no_follow};
for my $rel (@$rels) {
-
# don't follow rels to where we came from
next
if defined $attrs->{from}
&& $attrs->{from} eq $rs->related_source($rel)->result_class;
-
+
my ($block)
- = grep { !$_->is_field }
+ = grep { !$_->is_field || $_->multi_value }
@{ $base->get_all_elements( { nested_name => $rel } ) };
next if !defined $block;
@@ -481,6 +483,41 @@
from => $dbic->result_class,
} );
}
+ else {
+ # has_one or might_have relationship
+
+ my $info = $dbic->result_source->relationship_info($rel);
+
+ my @fpkey = $dbic->related_resultset($rel)->result_source->primary_columns;
+
+ croak 'multiple primary keys are not supported for has_one/might_have relationships'
+ if(@fpkey > 1);
+
+ my $fpkey = shift @fpkey;
+ my ($fkey, $skey) = %{$info->{cond}};
+ $fkey =~ s/^foreign\.//;
+ $skey =~ s/^self\.//;
+
+ my $fclass = $info->{class};
+
+ croak 'The primary key and the foreign key may not be the same column in class '.$fclass
+ if $fpkey eq $fkey;
+
+ my $schema = $dbic->result_source->schema;
+ # use transactions if supported by storage
+ $schema->txn_do(sub {
+
+ # reset any previous items which were related to $dbic
+ $rs->schema->resultset($fclass)->search({ $fkey => $dbic->$skey })->update({ $fkey => undef });
+
+ # set new related item
+ my $updated = $rs->schema->resultset($fclass)->search( { $fpkey => $params } )->update({ $fkey => $dbic->$skey });
+
+ $schema->txn_rollback
+ if $updated != 1;
+
+ });
+ }
}
}
@@ -744,7 +781,9 @@
{
$dbic->set_column( $accessor, $value );
}
- elsif ( $dbic->can($accessor) ) {
+ elsif ( $dbic->can($accessor)
+ # and $accessor is not a has_one or might_have rel where the foreign key is on the foreign table
+ and !$dbic->result_source->relationship_info($accessor)) {
$dbic->$accessor($value);
}
else {
@@ -1164,7 +1203,8 @@
__PACKAGE__->table("review");
__PACKAGE__->add_columns(
- book => { data_type => "INTEGER" },
+ id => { data_type => "INTEGER" },
+ book => { data_type => "INTEGER", is_nullable => 1 },
review_text => { data_type => "TEXT" },
);
@@ -1190,6 +1230,23 @@
to have a field for the related table's primary key, as DBIx::Class will
handle retrieving the correct row automatically.
+You can also set a C or C relationship using a multi value
+field like L