http://qs321.pair.com?node_id=57260


in reply to CRSC

It's not a bad idea; but wouldn't it be better to: At least, that'd make editing the table, and working with a big table, simpler.

Replies are listed 'Best First'.
Re: Re: CRSC
by Corion (Patriarch) on Feb 22, 2001 at 14:58 UTC

    I like this idea, but it has the major drawback that a hash dosen't preserve order, and in this case the order of application of those REs is important.

    I don't know of any elegant solution to this (I'm using mostly the same method when creating multi-page CGI scripts), so the thing I'm using is a hash of page handlers and an array as the sequence of pages (yes, it's the dreaded wizard-style interface). Pages (== hash keys) that are not found in the sequence array are then either flagged as an error (more stability) or silently appended to the end of the wizard (quick'n'dirty development).

    A sample :
    my @pageorder = ( "welcome", "address", "recipients", "preview", "done +" ); # Routines to create the pages my %pages = ( "welcome" => \&page_welcome, "address" => \&page_address, "recipients" => \&page_recipients, "preview" => \&page_preview, "done" => \&page_done, ); # Routines to validate user input for every page my %validators = ( "welcome" => undef, "address" => \&validate_address, "recipients" => \&validate_recipients, "preview" => undef, "done" => undef, );

    And the page handler works like this :

    # First, determine where we are, using a default of "welcome" on error + : my $page; if ($cgi->param("go_prev") and $cgi->param("prevpage")) { $page = $cgi->param("prevpage"); } else { $page = $cgi->param("nextpage"); }; if (! exists $pages{$page}) { $page = "welcome"; }; # Parameter validation ommitted, as it's simply a walk of the validati +on chain for every page ... # Execute the special code for this page, so all this searching had so +me sense : &{$pages{$page}};

      You could always use Tie::IxHash for this. You can also cheat and do what I find myself doing sometimes:

      my @pages = ( welcome => \&page_welcome, address => \&page_address, recipients => \&page_recipients, preview => \&page_preview, done => \&page_done, ); my %pages= @pages; @pages= do { my $key= 0; grep { $key= !$key } @pages };
      Since you have two hashes with shared keys, you might go a different route like:
      my( @pageorder, %pages, %validators ); for( ["welcome", \&page_welcome, undef], ["address", \&page_address, \&validate_address], ["recipients", \&page_recipients, \&validate_recipients], ["preview", \&page_preview, undef], ["done", \&page_done, undef], ) { push @pageorder, $_->[0]; $pages{$_->[0]}= $_->[1]; $validators{$_->[0]}= $_->[2]; }
      or perhaps:
      use mapcar; my( @pageorder, %pages, %validators ); BEGIN { my( $key, $page, $valid )= mapcar {[@_]} ["welcome", \&page_welcome, undef], ["address", \&page_address, \&validate_address], ["recipients", \&page_recipients, \&validate_recipients], ["preview", \&page_preview, undef], ["done", \&page_done, undef]; @pageorder= @$keys; @pages{@$keys}= @$page; @validators{@$keys}= @$valid; }
      Season to taste.

              - tye (but my friends call me "Tye")