[Html-widget] Possible bug with undef in DBIx::Class::HTMLWidget?
    stephen joseph butler 
    stephen.butler at gmail.com
       
    Fri Mar 30 21:12:19 GMT 2007
    
    
  
(Apologies is this is the wrong list)
I'm trying to create a select list for a database key that is either
an integer or null. The code to do this looks something like this
(this is Catalyst and DBIx::Class):
package Foo::Controller::Bar;
# blah blah blah
sub widget {
  my ( $self, $c ) = @_;
  my $w = $c->widget( 'baz' );
  my @bazes = $c->model( 'Foo::Baz' )->search(
    undef,
    {
      select => [qw/id name/],
      order_by => 'name'
    } );
  $w->method( 'post' );
  $w->element( 'Select', 'baz_id' )
    ->label( 'Baz' )
    ->size( 1 )
    ->multiple( 0 )
    ->options( '' => '(none)', map { $_->id => $_->name } @bazes );
  return $w;
}
sub save : Local {
  my ( $self, $c, $id ) = @_;
  my $widget = $self->widget( $c );
  my $result;
  $widget->action( $c->uri_for( 'save', $id ) );
  $widget->element( 'Submit', 'save' )
    ->value( 'Save' );
  $result = $widget->process( $c->request );
  if ($result->has_errors) {
    # do stuff to redisplay the form
  } else {
    my $bar;
    if (defined $id) {
      $bar = $c->model( 'Foo::Bar' )->find( $id );
    } else {
      $bar = $c->model( 'Foo::Bar' )->create( {} );
    }
    $bar->populate_from_widget( $result );
    $c->response->redirect( $c->uri_for( 'list' ) );
  }
}
More code than I probably needed to show... but anyway, I change to
the '(none)' option and nothing happens. It doesn't save. Looking
through the code for DBIC::HTMLWidget I think the problem is here:
sub populate_from_widget {
	my ($dbic,$result)=@_;
    	croak('populate_from_widget needs a HTML::Widget::Result object
as argument')
        	unless ref $result && $result->isa('HTML::Widget::Result');
	#   find all checkboxes
    my %cb = map {$_->name => undef } grep {
$_->isa('HTML::Widget::Element::Checkbox') }
        $result->find_elements;
    foreach my $col ( $dbic->result_source->columns ) {
        my $col_info = $dbic->column_info($col);
        my $value = scalar($result->param($col));
        if ($col_info->{data_type} and $col_info->{data_type} =~
m/^timestamp|date|integer|numeric/i
            and defined $value and $value eq '') {
            $value = undef;
        }
        if (defined($value) and !ref($value) and $value eq 'undef') {
            $value = undef;
        }
        $dbic->$col($value)
            if defined $value || exists $cb{$col};
    }
    $dbic->insert_or_update;
    return $dbic;
}
Couple things:
1) The schema loader made my column data_type INT, which doesn't match
the regex.
2) When updating the baz_id column, it skips it because the value is
now undefined. That was the point!
Am I doing something wrong? I manually changed the code to look like
this, and it seems to work:
sub populate_from_widget {
	my ($dbic,$result)=@_;
    	croak('populate_from_widget needs a HTML::Widget::Result object
as argument')
        	unless ref $result && $result->isa('HTML::Widget::Result');
	#   find all checkboxes
    my %cb = map {$_->name => undef } grep {
$_->isa('HTML::Widget::Element::Checkbox') }
        $result->find_elements;
    foreach my $col ( $dbic->result_source->columns ) {
        my $col_info = $dbic->column_info($col);
        my $value = scalar($result->param($col));
        next unless defined $value || exists $cb{ $col };
        if ($col_info->{data_type} and $col_info->{data_type} =~
m/^timestamp|date|int|numeric/i
            and defined $value and $value eq '') {
            $value = undef;
        }
        if (defined($value) and !ref($value) and $value eq 'undef') {
            $value = undef;
        }
        $dbic->$col($value);
    }
    $dbic->insert_or_update;
    return $dbic;
}
    
    
More information about the Html-widget
mailing list