hesco has asked for the wisdom of the Perl Monks concerning the following question:

UPDATE:

Well, I'm moving forward, and yesterday morning rolled out a version 0.10 beta for some live testing just this last night. The following is my now working cgi script which calls the module I've been working on. I'd love to move this logic into the module itself and simplify the interface to the module, using it to hide all the complicated pieces of this. But for the moment, this seems to be working. The $pb->{'q'} is a CGI object, which permitted me to use the ->delete() method to undefine the parameters which were highjacking the execution and routing my logic into ->obtain_next_household() before it did its ->_record_call_results() thing. I also renamed my object, from $dashboard to $pb, for phonebank. Seemed for intuitive and informative.

Once I got this program flow issue sorted out, working through all the other issues about the database interactions has been fairly straightforward. I'm now collecting some useful data about these calls.

Our first user spent about ninety minutes on the phone with the application last night. I guess next I need to work on the reporting methods so we can generate a useful dashboard of stats from the calls, give our users some encouraging feedback.

My first round of live tests also revealed some gotchas I'll spend time on Monday documenting. If things are not appropriately aliased in the queries defined in the config file, the application seems to work -- doesn't throw any show stopping errors, but also doesn't reveal any data about the households to be called, including any phone number to call. That seemed like an important thing to get into the perldoc for the module.

-- Hugh

#!/usr/bin/perl -T use strict; use warnings; use Carp; use Data::Dumper; use lib qw{/home/hesco/sandbox/Politics-VoterContact-PhoneBank/lib}; use Politics::VoterContact::PhoneBank::DB; use Politics::VoterContact::WWW::Dashboard2; my %defaults = ( config_file => '/home/hesco/sandbox/Politics-VoterContact-P +honeBank/t/conf.d/pb-ListCheckOut_same_db_off.ini', ); my $pb = Politics::VoterContact::WWW::Dashboard2->new(\%defaults); my $params = $pb->{'q'}->Vars; print STDERR "The cgi script says form gave us: \n" . Dumper(\$params) +; my ($hh_values); if($pb->{'q'}->param('_submit') eq 'Proceed to Next Household'){ $pb->_record_call_results($params); $hh_values = $pb->_obtain_next_household(); print STDERR "The cgi scripts says \$hh_values is: " . Dumper(\$hh_v +alues); $pb->{'q'}->delete('_submit'); $pb->{'q'}->delete('_submitted_phone_canvas_household'); } elsif(!$pb->{'q'}->param('_submitted_phone_canvas_household')){ $hh_values = $pb->_obtain_next_household(); print STDERR "The cgi scripts says \$hh_values is: " . Dumper(\$hh_v +alues); } my $html = $pb->_render_online_household_form($hh_values); print STDERR "We made it back to cgi script.\n"; if(defined($html)){ # print STDERR "canvas_hh_screen.cgi says that \$html is: $html \n"; print $html; } else { print STDERR "\$html remains undefined for some reason.\n"; } 1;

Maybe its the head cold I'm nursing this week. I don't know. But no matter how I try this, I can not seem to get this to work out right.

I'm writing a module to manage a predictive dialing operation. A configuration file defines a query for obtaining a list of households, and another query for obtaining the residents in that household. My $dashboard->_render_online_household_form() method does a fine job of displaying data from the database about the household and its residents. It collects data and will use CGI::FormBuilder->confirm() method to display the collected data just fine.

The confusion gets introduced when I try to add in a method called: $dashboard->_process_list_of_households(). Even attempts to use a simplified ->_obtain_next_household() method seem to lead to confusion. My ->_record_call_results($field) method is skipped entirely and fed the form and logs renders the subsequent household, instead of storing in the database first the results of the previous call.

sub _render_online_household_form { my $self = shift; my $hh_values = shift; my $form = CGI::FormBuilder->new( name => 'phone_canvas_household', method => 'post', stylesheet => '', values => $hh_values, title => 'Phone Canvas a Household', submit => ['Reset this Household', 'Proceed to Next Househ +old','Save Results'], keep_extras => 1, sticky => 1, ); my $mode; if(defined($hh_values->{'hh_id'})){ my $mode = $form->cgi_param('mode') || 'canvas'; } else { $hh_values = $self->_obtain_next_household(); $form->cgi_param( name => 'mode', value => 'next_hh' ); } # lots of form field definition statements if($mode eq 'canvas'){ print STDERR "Our mode is 'canvas'. \n"; if($form->submitted && $form->validate){ my $field = $form->fields; if($form->submitted eq 'Proceed to Next Household'){ print STDERR "\$form->submitted is now: " . $form->submitted . + "\n"; $self->_record_call_results($field); my %field_options = ( name => 'mode', type => 'hidden', value => 'next_hh', ); $form->field( \%field_options ); $www_hh_form = $form->render(header => 1); # $www_hh_form .= "<pre>" . Dumper(\$field) . "</pre>"; return $www_hh_form; } elsif($form->submitted eq 'Save Results') { $self->_record_call_results($field); # $www_hh_form = $form->confirm(header => 1); $www_hh_form = $self->_render_dashboard(); $www_hh_form .= "<pre>" . Dumper(\$field) . "</pre>"; print STDERR "\$form->submitted is now: " . $form->submitted . + "\n"; return $www_hh_form; } elsif($form->submitted eq 'Reset this Household') { my $record_count = $self->_reset_hh_call_results($field); $www_hh_form = $form->render(header => 1); print STDERR "\$form->submitted is now: " . $form->submitted . + "\n"; return $www_hh_form; } else { print STDERR "Form invoked with illegal submit button from IP: + \n"; die "Form invoked with illegal submit button from IP: \n"; } } else { print STDERR "OK, we'll render form for first time for this hous +ehold.\n"; print STDERR "\$form->submitted is now: " . $form->submitted . " +\n"; $www_hh_form = $form->render(header => 1); return $www_hh_form; } } elsif($mode eq 'next_hh'){ print STDERR "Our mode is 'next_hh'. \n"; $self->_obtain_next_household(); my %field_options = ( name => 'mode', type => 'hidden', value => 'canvas', ); $form->field( \%field_options ); } }
My testing has been focused on what happens when I hit the 'Proceed to Next Household' button. The readmore tags hide what the logs look like the first time through:

[Wed May 14 21:03:31 2008] [error] [client 127.0.0.1] line 185 of ->_o +btain_next_household() checked out record with code: Now Assigned. [Wed May 14 21:03:32 2008] [error] [client 127.0.0.1] Our mode is 'can +vas'. [Wed May 14 21:03:32 2008] [error] [client 127.0.0.1] OK, we'll render + form for first time for this household. [Wed May 14 21:03:32 2008] [error] [client 127.0.0.1] $form->submitted + is now: 0 [Wed May 14 21:03:32 2008] [error] [client 127.0.0.1] We made it back +to cgi script.
On that form, I hit a checkbox indicating I spoke with a household resident, update the status selector to indicate the call results and choose 'Proceed to Next Household'. Then in the logs, I get:
[Wed May 14 21:07:15 2008] [error] [client 127.0.0.1] line 185 of ->_o +btain_next_household() checked out record with code: Now Assigned., r +eferer: http://localhost/cgi-bin/canvas_hh_screen.cgi [Wed May 14 21:07:16 2008] [error] [client 127.0.0.1] Our mode is 'can +vas'. , referer: http://localhost/cgi-bin/canvas_hh_screen.cgi [Wed May 14 21:07:16 2008] [error] [client 127.0.0.1] $form->submitted + is now: Proceed to Next Household, referer: http://localhost/cgi-bin +/canvas_hh_screen.cgi [Wed May 14 21:07:16 2008] [error] [client 127.0.0.1] ->_record_call_r +esults() says: $VAR1 = \\{, referer: http://localhost/cgi-bin/canvas_ +hh_screen.cgi [Wed May 14 21:07:16 2008] [error] [client 127.0.0.1] 'h_4 +380' => {, . . . followed by a Data::Dumper hash for the subsequent hou +sehold, . . . [Wed May 14 21:07:16 2008] [error] [client 127.0.0.1] $list->_CheckInR +ecord_VoterID() says that $args consists of: $VAR1 = \\{, referer: ht +tp://localhost/cgi-bin/canvas_hh_screen.cgi . . . where it attempts to checkin the new record, not the ju +st completed one . . . [Wed May 14 21:07:16 2008] [error] [client 127.0.0.1] };, re +ferer: http://localhost/cgi-bin/canvas_hh_screen.cgi [Wed May 14 21:07:16 2008] [error] [client 127.0.0.1] We made it back +to cgi script., referer: http://localhost/cgi-bin/canvas_hh_screen.cg +i
with no evidence in the log or database that the just canvassed household has been checked back in, to the database.

And for the cgi script which calls this module, it reads simply:

#!/usr/bin/perl -T use strict; use warnings; use Carp; use Data::Dumper; use lib qw{/home/hesco/sandbox/Politics-VoterContact-PhoneBank/lib}; use Politics::VoterContact::PhoneBank::DB; use Politics::VoterContact::WWW::Dashboard; my %defaults = ( config_file => '/home/hesco/sandbox/Politics-VoterContact-P +honeBank/t/conf.d/pb-ListCheckOut_same_db_off.ini', ); my $dashboard = Politics::VoterContact::WWW::Dashboard->new(\%defaults +); # my $html = $dashboard->_process_list_of_households(); my $hh_values = $dashboard->_obtain_next_household(); my $html = $dashboard->_render_online_household_form($hh_values); print STDERR "We made it back to cgi script.\n"; if(defined($html)){ # print STDERR "canvas_hh_screen.cgi says that \$html is: $html \n"; print $html; } else { print STDERR "\$html remains undefined for some reason.\n"; } 1;
I have tried moving the calls to ->_obtain_next_household() around. From the calling cgi script, into the dispatch logic of this CGI::FormBuilder based code. Nothing I seem to do changes the results much. And no quantity of garlic, ginger, pepper miso soup seems to make my head think any more clearly about this issue.

Can someone please point out what is surely an obvious blunder I am making and overlooking? This has proven maddening.

-- Hugh

if( $lal && $lol ) { $life++; }

Replies are listed 'Best First'.
Re: Troubles w/ CGI::FormBuilder dispatch logic
by Anonymous Monk on May 15, 2008 at 07:53 UTC
    Can someone please point out what is surely an obvious blunder I am making and overlooking?

    Sorry, its too hard to follow, but I did notice $mode is always undefined

    my $mode; ######### this one always undefined if(defined($hh_values->{'hh_id'})){ my $mode = $form->cgi_param('mode') || 'canvas'; ########### NEW VARIABLE CALLED MODE } else { $hh_values = $self->_obtain_next_household(); $form->cgi_param( name => 'mode', value => 'next_hh' ); }
      Yes, thank you. I had already fixed that in my sandbox, after copying the code into the SoPW page. -- Hugh
      if( $lal && $lol ) { $life++; }
Re: Troubles w/ CGI::FormBuilder dispatch logic
by Starky (Chaplain) on May 15, 2008 at 14:30 UTC
    There's an awful lot of code and output to parse there for someone unfamiliar with your setup.

    A friendly suggestion: Try to boil your problem down into the simplest bit of functionality possible with a minimal amount of actual code. If you haven't discovered your problem by that point, repost your minimal formulation of the problem and you'll likely get timelier and more accurate responses.