in reply to abstraction -- level up!

If you are able to remove the code that is specific to each selection (i.e., the comparison used to assign a SELECTED element to your result set), than your database code can be generalized (like the code provided by dragonchild above).

It appears that you are using CGI::Application. I assume from your code that your template has something like the following for the <TMPL_LOOP> inside a <select> list:
<select name=city_id> <TMPL_LOOP cities> <option value="<TMPL_VAR id>" <TMPL_IF selected>selected</TMPL_IF>> <TMPL_VAR city_name> </TMPL_LOOP> </select>
If so, the following suggestion may help.

You can simplify using HTML::FillInForm. First, remove the logic from your template:
<select name=city_id> <TMPL_LOOP cities> <option value="<TMPL_VAR id>"><TMPL_VAR city_name> </TMPL_LOOP> </select>

Next, update your database selection code (remove the loop that assigns a SELECTED element):
sub _getBuilderList { my $self = shift; my $sth = $self->param('DBH')->prepare("SELECT id, city_name FROM ci +ty ORDER BY city_name" ); $sth->execute(); # returns a reference to an array of hash refs my $cities= $sth->fetchall_arrayref( {} ); $sth->finish; return $cities; }

Next, let HTML::FillInForm handle the selection for you:
my $city_list= $self->_getBuilderList; # ... my $template= $self->load_tmpl( ... ); $template->param( cities => $city_list, # ... ); require HTML::FillInForm; return HTML::FillInForm->new->fill( scalarref => \$template->output, fobject => $self->query, );

This assumes that the selection (in this case, city_id) is passed in as a form parameter. If not, you can assign it yourself:
$self->query->param( city_id => $some_value ); # HTML::FillInForm code as before

Now _getBuilderList can be simplified to use a general prepare/select routine:
sub _getBuilderList { my $self = shift; my $sql = q{ SELECT id, city_name FROM city ORDER BY city_name }; return selectall_sql( $self->param('DBH'), $sql ); } # (needs proper error handling) sub selectall_sql { my( $dbh, $sql, $values )= @_; $values ||= []; + my $results= $dbh->selectall_arrayref( $sql, { Slice => {} }, @$values ); + return $results if $results; + warn $dbh->err if $dbh->err; + return; }

--sacked