[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [MacPerl-WebCGI] [MacPerl] Referencing a Hash element...



Title: Re: [MacPerl-WebCGI] [MacPerl] Referencing a Hash element...
Thanks for the response Bruce,

All of your assumptions are correct, and the code you have supplied is exactly what I was trying to achieve (basically improving readability for future expansion - as I suspected, I was overcomplicating the referencing syntax and tying myself in knots), but your comments lead me to question the assumptions I have made myself.

In a nutshell, I am building a script that allows myself and my non-html colleague to make changes to our site via the Internet. I have started off with a script that allows me to modify a series of text links which will appear on every page. You can see the text links in place at

http://www.team-artonomy.com/previewIndex.html

The CGI script reads in a file which contains the raw text data of 'link text' (the clickable bit), 'description' (which appears in the status bar - using JavaScript - and the 'title' attribute of the <a href> tag), and location (the URL). This data is presented in to an HTML form, with each of the above text fields as editable input fields, along with a checkbox to determine whether the link will be used, and the order they will appear in the HTML, as follows:

For each line of text in the data file, split it into $linktext, $description and $location, then output the following html:

<input type=checkbox name="use$tagIndex" value=yes $checked></td>
<input type=text name="linktext$tagIndex" value="$linktext" size=14 maxlength=14></td>
<input type=text name="description$tagIndex" value="$description" size=40></td>
<input type=text name="location$tagIndex" value="$location" size=30></td>
<input type=text name="order$tagIndex" value="$tagIndex" size=2 maxlength=2></td>

The links can then be edited, and the code snippet I originally supplied (repeated below), is the section which checks each input field to make sure it is a valid entry. If any entries are invalid, the form is generated again with appropriate error messages. If it is okay, then the links are complied into an HTML preview. If this is approved, the data file is re-written, and the HTML formatted links are written to a file which is then used as an SSI. This is all handled by the same CGI, with changes to the 'action' name/value pair determining what is done with the form data. I am pre-formatting the SSI because changes to the raw data will not be very frequent, so it seemed to make sense to format the HTML once each time the data changes, rather than reading in the raw data and formatting it 'on the fly'.

I realise this is a sledgehammer to crack a walnut, but my main aim is to understand the underlying principles of an admin script. It would obviously be much easier to just re-write the raw text file in BBEdit and use an SSI to include it, but that is not the object of the exercise.

If, as Bruce intimated, someone could suggest a more efficient method or structure for the data (if you can follow my ramblings), I would certainly appreciate it before I head off too far in the wrong direction. I am first and foremost an illustrator who has dabbled with programming since the heady days of 6502 assembly language, so I am feeling a little out of my depth now it is getting serious. =)

TIA, and my apologies for the bulky post.

Richard

[Code snippet]
****************************************************************************

 $tagIndex = 1;

 while (exists $Form{"linktext$tagIndex"}) {
   #  Check the data fields for errors
   if (exists $Form{"use$tagIndex"}) {
     #  Removing any trailing newlines
     chomp (
     $Form{"linktext$tagIndex"},
     $Form{"description$tagIndex"},
     $Form{"location$tagIndex"},
     $Form{"order$tagIndex"}
     );
     &buildErrorMessage('you have left blank fields') if (
     $Form{"linktext$tagIndex"} eq '' or
     $Form{"description$tagIndex"} eq '' or
     $Form{"location$tagIndex"} eq '' or
     $Form{"order$tagIndex"} eq '');

   # Check each entry for illegal characters.
   # Blocks are enclosed in braces to contain the scope
   # of the $& variable
   {
   # Substitute any illegal characters with an asterisk
   $Form{"linktext$tagIndex"} =~ s/[^a-zA-Z ]+/\*/g;
   # Throw an error if a character was replaced
   &buildErrorMessage(qq| the link text in line $Form{"order$tagIndex"} contained an illegal character '$&'|) if $&;
   }
   {
    #  Trim whitespace from each end
   $Form{"linktext$tagIndex"} =~ s/^\s*(.*?)\s*$/$1/;   
   }
   {
   # Substitute any illegal characters with an asterisk
   $Form{"description$tagIndex"} =~ s/[^a-zA-Z()., ]+/\*/g;   
   &buildErrorMessage(qq| the description in line $Form{"order$tagIndex"} contained an illegal character '$&'|) if $&;
   }
   {
   $Form{"description$tagIndex"} =~ s/^\s*(.*?)\s*$/$1/;
   # Now make sure there is a full stop on the
   # end of the description.
   # Add a full stop to the end of the description
   $Form{"description$tagIndex"} .= '.';
   #  If there are two fullstops, replace with one
   $Form{"description$tagIndex"} =~ s/\.+$/\./;
   ucfirst $Form{"description$tagIndex"};
   }
   {
   $Form{"location$tagIndex"} =~ s/[^a-zA-Z_#\/.:]+/\*/g;
   &buildErrorMessage(qq| the location in line $Form{"order$tagIndex"} contained an illegal character '$&'|) if $&;
   }
   }
   $tagIndex++;
 }

****************************************************************************

--- Bruce Van Allen <bva@cruzio.com> wrote:
> At 8:40 PM 12/27/00, Richard Smith wrote:
> >Hello,
> >
> >Below is a snippet of code from a CGI script I am
> building. I have been
> >trying to work out how to create a reference to the
> hash elements to save
> >constant repetition of the full Hash element name
> (i.e.
> >$Form{"description$tagIndex"} ), but I am having no
> luck. I have read and
> >re-read the relevant section in 'Programming Perl',
> but i am none the wiser
> >as to the necessary syntax. Any pointers would be
> much appreciated. Please
> >feel free to rubbish my bloated code too.
>
> [big snip of code]
>
> Richard -- Please clarify: When you say you want to
> "save constant
> repetition of the full Hash element name (i.e.
> $Form{"description$tagIndex"} )", do you mean to
> save typing time, to
> conserve bytes/electrons, to avoid excessive
> accesses of a variable,
> to make your code easy for someone else to
> understand, to make your
> code "elegant", or what?
>
> Except for "elegance" -- a suspect goal IMO (poetry
> reveals, elegance
> conceals; but that's another topic... ;-) -- these
> various and
> sometimes conflicting goals might all benefit from
> some higher-level
> structural changes in how you're processing your
> form input. I'm not
> sure how much you'd gain from using references, but
> maybe I'm not
> seeing your big picture here. It would help to have
> an outline of the
> whole process.
>
> What I gather is that you have some base hash keys
> (linktext,
> description, location, order, ...), and you're also
> iterating through
> some series of $tagIndex (although your code snippet
> doesn't show
> what terminates that series), so you have a bunch of
> hash elements
> like $Form{description1}, $Form{description2}, ...,
> $Form{linktext1},
> $Form{linktext2}, ...
>
> And you're doing several things to some or all of
> those hash elements:
> -remove line-endings
> -trim whitespace
> -replace non-alphas with '*'
> -terminate (description elements) with '.'
> -populating an error message as needed
>
> This could be handled efficiently with some lists
> and loops, but I'd
> rather not make them up without being sure what your
> process is.
>
> OTOH, if I'm just going off on my own jag, here's
> what might be an
> answer to your literal question about employing
> references:
>
> #####
>
> #!perl -w
>
> my %Form;
> my $tagIndex = 1;
>
> $Form{"description$tagIndex"} = ' A big %!@#$& dog
> with 0-0 eyes ... ';
>
> # make a reference with preceding '\'
> my $Fd = \$Form{"description$tagIndex"};
>
> # process ref (de-referenced with preceding '$')
> # trim
> $$Fd =~ s/^\s*(.*?)\s*$/$1/;
>
> # full stop at end (Yanks call it a period)
> $$Fd =~ s/\s*\.*$/./;        # Do this *before* next
> step
>
> # censor
> $$Fd =~ s/[^a-zA-Z .]+/*/g;  # Don't need to escape
> the *
>                               #  in the replacement
> side of s///
>                               # Also: add '.' to OK
> chars
>
> # Lo, the original value has been processed
> print $Form{"description$tagIndex"};
>
> __END__
>
> prints:
> A big * dog with * eyes.
>
> Anyway, I still think you'd gain more by
> re-structuring. Clarify the
> process, and someone might be able to suggest a
> wholistic solution.
> Looks like a case for the power of 'map'. (Master
> map and you move to
> the next tier ...)
>
> 1;
>
>
> - Bruce
>
> __Bruce_Van_Allen___Santa_Cruz_CA__
--

Richard Smith
Artist/ Illustrator/ Site Designer

Team Artonomy,
Drawing Business

http://www.team-artonomy.com
richard@team-artonomy.com
ICQ #29343811