The replies are all very helpful so far - thanks. I will do more research into table-driven prog. and MVC on monday. I thought it might also be useful to offer some more detail on my page o' code. Here's an outline as I can remember it on a sunny Sat. afternoon at the local lib. on monday i might post a few snippets of code for review...
<%once> my $none; my $groupname = undef; use Carp::Assert; use WorkingSet::SetContainer; use SearchUtil; </%once> <%perl> my $session = $m->session(); #warn Dumper %ARGS2,"ARGS@@@@@" if DEBUG; my $orig_action = $ARGS2{action}; warn "original action is $orig_action" if DEBUG; my $dbh = pgconnect(); my @time = (localtime); $| = 1; my $refreshNavBar=0; #make sure the user has a working set object. my $workingSet = resultUtil::prep_working_set($session->{workingset}); #there are two pulldown menus. $ARGS2{switch} = $ARGS2{switch1} if $ARGS2{switch1}; $ARGS2{switch} = $ARGS2{switch2} if $ARGS2{switch2}; #user is downloading a file. my $genome_ws_view; if($ARGS2{setview}) { warn "setview is set" if DEBUG; $workingSet->setview($ARGS2{setview}); $genome_ws_view = 1 if $ARGS2{setview} eq "S"; } if($ARGS2{"download"}) { warn "download" if DEBUG; #warn Dumper "ARGS2", %ARGS2; %ARGS2 = $m->comp('.download', display => $ARGS2{download}); } elsif(not %ARGS2) { #warn "getting last args" if DEBUG; #warn Dumper %ENV, "ENV"; # don't get last args if they just downloaded a file if($ENV{SCRIPT_URI} =~ /search|html$/) { #then don't reset the args. } else # unless($session->{download} eq "excel") { %ARGS2 = $m->comp('.need_args'); } } elsif($ARGS2{switch}) { # just like Apple. do the switch. #warn "switching $ARGS2{switch}" if DEBUG; # check that there is a SetContainer. if(ref $session->{set_container} eq "WorkingSet::SetContainer") { # double check the set exists. if($session->{set_container}->contains($ARGS2{switch})) { $session->{set_container}->active($ARGS2{switch}); $session->{working_set} = $session->{workingset} = $workingS +et = $session->{set_container}->get_active; %ARGS2 = %{$session->{last}} if ref $session->{last} eq "HAS +H" && scalar keys %ARGS2 == 1; } else { warn "not switching - set doesn't exist anymore" if DEBUG + } } else {warn "not switching - no set container" if DEBUG}; } #do this after we've updated to a new set if they switched sets. $genome_ws_view = $workingSet->setview eq "S" && $orig_action =~ /vie +w/ ? 1 : 0; #warn Dumper $workingSet, "WOKRINGSET"; #warn Dumper "set view?", $workingSet->setview,$ARGS2{action} if DEBUG +; if($ARGS2{"update_ws"}) { warn "updating working set" if DEBUG; %ARGS2 = $m->comp('.working_set', ws => $ARGS2{ws}, workingSet => +$workingSet, checkbox => $ARGS2{checkbox}, action => $ARGS2{action}); #warn Dumper %ARGS2, "args 2"; $workingSet = $session->{working_set}; #if we just added something to a set, so cached search results. } my %results; my $comp; my $using_cache; if($ARGS2{action} =~ "prev_") { warn "using cached search results"; $using_cache=1; ($comp, %results) = SearchUtil::get_saved_search($session, $ARGS2{ +action}); #warn "comp is $comp"; } else { for(qw(offset mine omitfrags print translate nosqueeze)) { $ARGS2{$_} ||= 0; } #some other default values. my $relArrRef; $ARGS2{"nucorpro"} = "nuc" unless($ARGS2{"nucorpro"}); #save the order preference for later in the session for the views +and such. $ARGS2{orderby} = resultUtil::getOrderBy($ARGS2{orderby}, $session +->{orderby}); #warn "ORDERBY is $ARGS2{orderby}" if $DEBUG; $ARGS2{"num"} = 100 unless ($ARGS2{"num"}); # displayed stuff my $layerToShow = 0; # default layer # } #print STDERR "groupname:$session->{user}\n"; if ($ENV{'HTTPS'} && $ENV{'HTTPS'} =~/on/i) { $groupname = uc $session->{'user'}; } #probably need to make sure they are viewing the working set as we +ll. # not sure if it does make sure of it. $session->{genome_ws_view} = $genome_ws_view; warn "genome ws view" if $genome_ws_view; $ARGS2{action} = "genome" if $workingSet->setview eq "S" && $ARGS2 +{action} =~ /view/; warn "action is $ARGS2{action}"; #warn Dumper %ARGS2,"ARGS2"; # returns a ViewResult, AlignmentResult2 or SearchResult object my $action_obj = Search::ResultFactory->new($ARGS2{action}, \%ARGS2); for(qw (orderby omitfrags showother)) { $session->{$_} = $ARGS2{$_}; } my %minisession; my @mini_keys = qw(bigtotal showother where top alignment_links); @minisession{@mini_keys} = @{$session}{@mini_keys}; for(qw(session dbh r env_https workingset working_set set_containe +r xml)) { delete $ARGS2{$_}; } #warn Dumper $ARGS2{scope}, $ARGS2{superscope}; $ARGS2{scope} = "checked" if $ARGS2{superscope}; $ARGS2{scope} = "all" if $ARGS2{superscope} eq "all"; my @checked = $m->comp("/components/get_set_choice.cmp", scope => +$ARGS2{scope}, setlist => $ARGS2{superscope}); #have to be careful, the %ARGS2 may contain some of these other va +lues. my @uri = split(/\//, $r->uri); #warn Dumper $workingSet; assert($workingSet->isa("WorkingSet"), "need working set") if DEBU +G; my %arguments = ("dbh" => $dbh, "session" => \%minisession, "r" => $r, "groupname" => $groupname, "env_https" => $ENV{HTTPS}, workingset => $workingSet, uri => $uri[0]."/search/index.html", user_agent => $ENV{HTTP_USER_AGENT}, genome_detail => $genome_ws_view, ); $arguments{checked} = \@checked if @checked; my $time = time; warn "startingprepareResult", ref $action_obj if DEBUG; # do the actual work %results = $action_obj->prepareResult(%arguments); $comp = $action_obj->{component}; # handle the results #warn Dumper %results; if(exists $results{error}) { warn "error calling error page. $results{error}"; $m->comp("/components/error.cmp", message => $results{error}); Apache::exit; } elsif(exists $results{message}) { $m->comp("/components/nothing.cmp", message => $results{messag +e}); Apache::exit; } delete $ARGS2{download}; delete $ARGS2{display}; #session and/or ARGS2 may need updating now. if(ref $results{session} eq "HASH"){ for(keys %{$results{session}}) { $session->{$_} = $results{session}->{$_} unless ref $results +{session}->{$_}; } } $session->{last} = \%ARGS2; @ARGS2{keys %{$results{args}}} = values %{$results{args}} if (ref( +$results{args}) eq "HASH"); $session->{alignment_links} = $results{results}->{alignment_links} + if ref $results{results} eq "HASH" && exists $results{results}->{ali +gnment_links}; for(keys %ARGS2, "clip", "alnseg", "protein", "pos3", "action", "h +species", "colorcode", "doprosite", "prosite" ,"repeat", "neg", "show +_length") { $session->{$_} = $ARGS2{$_}; } } # # The real output at last. # $m->comp($comp, args => $results{results}); # # # If we just performed a search, save the results so we can save a db +query later if they want to view the results again. # if($ARGS2{action} =~ /^(genome|search)/ && $ARGS{download} ne "excel") { $session->{download} = undef; SearchUtil::save_search_results($session, $ARGS2{action}, $results +{results}, $comp); assert(ref $session->{"prev_$ARGS2{action}"}, "didn't cache") if D +EBUG; #warn "SET the CACHE!" if DEBUG; } </%perl> <%cleanup> $dbh->disconnect() if $dbh; </%cleanup> <%flags> inherit=>undef </%flags> <%def .download><%perl> # have to have the def block on the same line as the perl block or el +se we get a newline in the file. my $session = $m->session; #set args from the session my @sessionArgs = grep(!/display/,keys %{$session}); %ARGS = (); %ARGS= %{$session->{last}} if ref $session->{last} eq "HASH"; $ARGS{display} = $display; # want the session args that were just used before the download requ +est. return %ARGS; </%perl> <%args> $display </%args></%def> <%def .need_args><%perl> my $session = $m->session; # if there are no arguments, reuse the old ones from the session. # it would be nice to just get the keys that should be ARGS2, not a +ll that other stuff like workingset, and so on. my @keys = grep(!/workingset/, keys %{$session}); @keys = grep(!/checkbox/, @keys); for(keys %{$session}) { $ARGS{$_} = $session->{$_}; } return %ARGS; </%perl> </%def> <%def .working_set><%args> $ws $workingSet $checkbox $action </%args> <%perl> my $session = $m->session; #warn Dumper "PATH",$ENV{PATH}; if($ws eq "clear") { #warn "clearing working set" if DEBUG; $workingSet->clear; $session->{workingset} = $workingSet; $session->{working_set} = $workingSet; $action = "view"; } elsif($ws eq "add") { $action = "prev_".$action; $workingSet->takeWorkingSetAction($ws,$checkbox) if $ws; } else { #warn "chckbox", $checkbox; #warn "ref", ref $workingSet; $workingSet->takeWorkingSetAction($ws,$checkbox) if $ws; $action = "view"; } my %new_args= %{$session->{last}} if ref $session->{last} eq "HASH"; %new_args = (action => $action, ah => 1) unless ref $session->{last} + eq "HASH"; delete $new_args{ws}; delete $new_args{update_ws}; delete $new_args{checkbox}; $session->{working_set} = $session->{workingset} = $workingSet; return %new_args; </%perl> </%def> <%args> %ARGS2 </%args>

# all the args are accessed via %ARGS. so sometimes some of these values need initializing to a default value.

# some more messing around with args, and calling of sub components (you know, the ones that look like <% .download %>, or something like that. Its the weekend - i can't promise to have perfect syntax.)

# I have a .working_set component, (where the user saves data - this component updates, deletes, or empties these sets).

# Also I have a .download component that handles when the user wants to download, say, an Excel file. For some reason, I felt it necessary to keep those two within the scope of the page, rather than move them out into their own components.

# are they viewing Previous Search Results? - if so, use the mason cache.

# call a factory class that determines what action we are taking (search, alignment, etc.) and returns the appropriate object.

# prepare parameters to pass into this new object when we call the method prepare_results

#call the object method mentioned above.

# now, update the session with any altered values that happen as a result of calling the method.

# look at the results. call the appropriate component - check for error or warning message, and call that component if necessary.

#otherwise, call component assoc. with object.

# update session to have the last set of ARGS in case we have to go back.

# if the action was a search or genome search, save the search results in the mason cache.

And at this point, I go take a coffee break.

In reply to Re: Handling different requests for a web app in one centralized place. by geekgrrl
in thread Handling different requests for a web app in one centralized place. by geekgrrl

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.