Mar
Stepping off the Rails; building a contact form in pure Ruby
If there’s a common knock I keep hearing against Ruby on Rails, it’s that it’s a heavy, full-stack solution that’s overkill for small problems – like contact forms and other one-pagers. I don’t disagree with that. Still, those people might not recognize that Ruby is a perfectly capable web development platform on its own, and can serve up dynamic markup with the best of ‘em. For fun, let’s put together a good old fashion cgi script to collect and fire off an e-mail using Ruby and some core libraries.
Back to basics
The first thing you need to know about CGI scripting: your Ruby script is executed by the web server, and any text it sends to stdout is captured and sent back to the user, whether it’s HTML, binary data, or something else. Armed with that fact, here’s a simple Hello, World app that will absolutely not impress you:
#!c:\ruby\bin\ruby.exe
# Required HTTP Header
puts "Content-Type: text/html"
puts
content = 'Hello World'
# Page content
puts '<html>'
puts ' <head><title>Sample App</title></head>'
puts ' <body>' + content + </body>'
puts '</html>'
Those puts method calls might not look so bad right now, but 50+ lines of code later, and you’ll be wishing there was a better way to generate markup. Fortunately, there is.
Embedded Ruby with ERB
Remember those RHTML files you’ve been writing in Rails? They’re actually parsed using ERB, a Ruby library for manipulating embedded Ruby templates. ERB also happens to be a core library, so including it is a snap. You can place the template in another file, but I’ll just use some heredoc statements to keep things all on one page.
Side note – .rhtml file extensions will become deprecated in favour of .erb in a future version of Rails
require 'erb'
...
content = 'Hello, World'
html_template = ERB.new <<-EOL # Heredoc
<html>
<head><title>Sample App</title></head>
<body> <%= content %> </body>
</html>
EOL
puts html_template.result
Building the form
We can’t send an e-mail without any data, so let’s rewrite the template to include input fields for our contact form. For the sake of keeping things simple, let’s just stick to a message body and a return e-mail address.
html_template = ERB.new <<-EOL # Heredoc
<html>
<head><title>Sample App</title></head>
<body>
<h1>Contact Us</h1>
<form method="post">
<p>E-mail<br/>
<input type="text" name="email"/></p>
<p>Message Body<br/>
<input type="textarea" name="message"/></p>
<input type="submit"/>
</form>
</body>
</html>
EOL
Note that the form submits to itself. Rendered in your browser, it looks a little something like this:
Capture user params with CGI
In order to get a hold of the values posted by the user, we’ll need to use the CGI library. It’s pretty darned easy – create a new instance of the CGI class and access its parameter hash as shown below:
...
require 'cgi'
cgi = CGI.new
return_addr = cgi['email']
message = cgi['message']
if return_addr.length > 0 && message.length > 0
# Send email here
end
# Build the contact form below
...
Send the e-mail with Net::SMTP
At this point, we should have everything we need to send the email. We can use ERB again to generate an e-mail template, and send it using Ruby’s Net::SMTP library....
if return_addr.length > 0 && message.length > 0
email_template = ERB.new <<-EOL
From: <%= return_addr %>
To: support@yourcompany.com
Subject: Contact Information
Date: <%= Time.local.strftime('%m-%d-%Y') %>
<%= message %>
EOL
require 'net/smtp'
Net::SMTP.start('your.smtp.server', 25) do |smtp|
smtp.send_message( email_template.result,
return_addr, 'supprt@yourcompany.com' )
end
end
# Build the contact form below
...
If you’d like to see the script in its entirety, click here: contact-form.rb
This is a pretty simple app, and we could easily expand upon it – indicate to the user that their e-mail was sent, do some validation on the fields, and so forth. Now that you’ve got all the tools, you should be able to figure out how and where these other pieces fit.
See Also: Ruby and the Web from Programming Ruby
Update: I’ve since updated this code to use Rack instead of plain CGI.

Commentary
Greetings Ben,
sorry for the offtopic (didn’t find a contact email address either), but I’d like to ask you where can I get your excellent Reddish theme for Mephisto, as your svn server seems offline.
Thanks for your help, my best regards: AndrĂ¡s
Good catch – it’s back up.
I was looking for exactly this as I am working on a one page site and thought “rails is overkill…” Thanks for the great article.
Awesome John – glad to hear someone found it helpful :)