Hal E. Fulton wrote:
> Hi guys, 
> 
> This is an offtopic post, which I rationalize in the 
> following ways:
>    1. I do plan ultimately to write CGIs in Ruby (though
>        I've done only the most primitive stuff so far)
>    2. I know this community to be a knowledgeable
>        and tolerant one
>    3. I'm atoning by posting a bit of Ruby code 
>        in the next message

I've written something similar, but a bit complexer.
I've created a formular definition (you could do this e.g. in XML, 
but Ruby code would suffice). This definition is then shown by a 
CGI script. 
If the user presses submit, then the formular-data is send to another 
CGI script which also reads in the formular definition (because there's 
a validation type in there) and checks each field for validation, 
and shows the whole formular with the new values, and if errors occured
the error messages next to the fields. 
And the formular data is stored in a XML-database (simple XML-file).

Of course this does not make sense if you want to show only one or two
formular, but if you plan to develop many formulars which look like each
other, then this could be a good idea.


> 
> My question is:
> 
> I've written a primitive CGI or two in the past, which will
> accept the data from a form and process it. Usually I
> error-check the input and give the user a "go back" 
> button if it isn't right.
> 
> Isn't there a technique for sort of encapsulating the whole
> thing, even the initial HTML? (I.e., generate the initial HTML
> from the CGI instead of static HTML that points to the 
> script?)

Let the CGI script create the HTML, by outputting HTML code.

> Something like:
>     If I have no input, display the blank form


# Submit-button: <input type="submit" name="submit" value="Send">

if cgi.has_key? "submit"
  # check for errors and redisplay the formular
else
  # output the blank formular
end


>     If I have input and the special invisible error fields are 
>       non-null, redisplay the form with the original input and
>       the error messages
>     If I have input and all is OK, process the input
> 
> I'd like to have a form with three columns (probably use
> tables): A column of labels like "Name:"; a column of
> text fields; and a column of blank invisible fields that 
> fill up with ugly red error messages on demand.
> 
> What is the general flow of such an animal? Can someone
> post a short example in Ruby, say with one or two fields? 
> I don't know much web stuff, and it always makes my brain 
> itch until I relearn the basics each time.

I'd do it like this (of course this should be extended):

# file: form.def
# formular definition
form {
  field :label => "Name",   :name => "name",   :validator => :NonEmpty
  field :label => "Street", :name => "street", :validator => :NonEmpty
}

######

# file: show.rb
# now the file that creates a HTML formular

require "cgi"

def form
  print %{
  <html><body><form method="POST" action="process.rb">
  <input type="hidden" name="formular" value="#{$formular}">
  }

  yield

  print %{
  </form></body></html>
  }
end

def field(h)
  value = # ... get the value from a database ?

  print %{
  <input type="text" name="#{ h[:name] }" value="#{value}">  
  }
end

def show_form(filename)
  eval File.readlines(filename).to_s
end

cgi = CGI.new
print "Content-type: text/html\r\n\r\n"
show_form(cgi["formular"][0] + ".def") 


# to show call: http://....../cgi-bin/show.rb?formular=form




######

# file: process.rb
# checks the input of the formular
 
require "cgi"
cgi = CGI.new


def form
  $str +=  %{
  <html><body><form method="POST" action="process.rb">
  }

  yield

  $str +=  %{
  </form></body></html>
  }
end

def field(h)
  value = $cgi[h[:name]][0]
  # validate here:
  #   you can write validator classes and then create an
  #   instance of it using: 
  #     val = eval "# { h[:validator] }.new }
  #     val.validate(value)

  $str += %{
  <input type="text" name="#{ h[:name] }" value="#{value}">  
  }

  if error then
    $str += "This field contains invalid input"
    $errors += 1
  end
end

def show_form(filename)
  eval File.readlines(filename).to_s
end

$str = ""
$errors = 0
$cgi = CGI.new
print "Content-type: text/html\r\n\r\n"
show_form(cgi["formular"][0] + ".def") 

if $errors == 0
  # no errors, do what you want
else
 print $str
end



##########

Well I've not tested this, but with some changes it should work.


Regards

Michael