Tuesday, February 06, 2007

Email Form Validation in Ruby on Rails Tutorial

This tutorial shows how to perform email form validation in Ruby on Rails using the built-in ActiveRecord::Validations framework with a non-persistent model.

Note: This tutorial assumes you already have Rails installed and have successfully created & configured a database for your environment.

Create a new Rails Project from the command line:
C:\temp> rails EmailFormValidation

Note: in order to leverage ActiveRecord validation, the application will need to be hooked into a database, so even though this example doesn’t talk to a database, one needs to be configured anyway:
Modify c:\temp\EmailFormValidation\config\database.yml to point to a locally running database:
adapter: mysql
database: depot_development
username: root
password: password
host: localhost

Install the BaseWithoutTable plugin so that we can validate the model without persistence:
C:\temp> cd EmailFormValidation
C:\temp\EmailFormValidation> ruby script/plugin install http://svn.viney.net.nz/things/rails/plugins/active_record_base_without_table/

Create c:\temp\EmailFormValidation\app\models\Contact.rb to use BaseWithoutTable and set up the email fields:
class Contact < ActiveRecord::BaseWithoutTable
column :name, :string
column :email_address, :string
column :enquiry, :string

validates_presence_of :name
validates_format_of :email_address, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
validates_length_of :email_address, :within => 5..255

def send_email
if save
return true #This tutorial does not cover Email configuration & sending
#return true if ApplicationMailer.deliver( ApplicationMailer.create_contact( self ) )
rescue Object => e

errors.add("There is a problem with our email system and this form could not be submitted")

Test the Model – the Contact Object should now have validation on save:
(note: If you have not correctly configured a database, you will see an error at this step along the lines of: Mysql::Error: Access denied for user: 'root@localhost')
C:\temp\EmailFormValidation> ruby script/console
>> c = Contact.new
=> #<Contact:0x487171c @new_record=true, @attributes={"name"=>nil, "enquiry"=>nil, "email_address"=>nil}>
> c.save
=> false
>> c
=> #<Contact:0x4823030 @errors=#<ActiveRecord::Errors:0x48217bc @base=#<Contact:

0x4823030 ...>, @errors={"name"=>["can't be blank"], "email_address"=>["is too short (minimum is 5 characters)", "is invalid"]}>, @new_record=true, @attributes=
{"city"=>nil, "company"=>nil, "name"=>nil, "enquiry"=>nil, "number_members"=>nil
, "state"=>nil, "email_address"=>nil}>
>> exit

Create c:\temp\EmailFormValidation\app\controllers\contact_controller.rb:
class ContactController < ApplicationController

def index
if request.post?
@contact_us_email = Contact.new(@params[:contact_us_email])

if @contact_us_email.send_email
flash[:notice] = 'Thank you for the email! We will get back to you ASAP =]'
@contact_us_email = nil

Create c:\temp\EmailFormValidation\app\views\contact\ (directory)
Create c:\temp\EmailFormValidation\app\views\contact\index.rhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<title>Contact Us</title>
<style type="text/css">
#contact_us_email label {position:absolute; text-align:right; width:250px;}
#contact_us_email input, #contact_us_email select, #contact_us_email textarea {margin-left:255px; margin-bottom:10px; width:180px;}
#contact_us_email select{width:50px;}
#contact_us_email label.required {text-align:left; font-style:italic; color:#B2B8CC;}
.fieldWithErrors {padding: 2px; background-color: red; display: table;}
#errorExplanation { width: 400px; border: 2px solid red; padding: 7px; padding-bottom: 12px; margin-bottom: 20px; background-color: #f0f0f0;}
#errorExplanation h2 { text-align: left; font-weight: bold; padding: 5px 5px 5px 15px; font-size: 12px; margin: -7px; background-color: #c00; color: #fff;}
#errorExplanation p { color: #333; margin-bottom: 0; padding: 5px;}
#errorExplanation ul li { font-size: 12px; list-style: square;}
#notice {color: green}
<p id="notice"><%= flash[:notice] %></p>
<%= start_form_tag %>
<%= error_messages_for 'contact_us_email' %>
<fieldset id="contact_us_email">
<legend>Contact Us </legend>
<label for="contact_us_email_name">Your Name:</label> <%= text_field(:contact_us_email, 'name', :size => 255) %> <label class="required">(required)</label><br/>
<label for="contact_us_email_email_address">Email Address:</label> <%= text_field(:contact_us_email, 'email_address', :size => 255) %> <label class="required">(required)</label><br/>
<label for="contact_us_email_enquiry">Comments or Questions?</label> <%= text_area(:contact_us_email, 'enquiry', :rows => 6) %><br/>
<label> </label> <%= submit_tag("Submit Enquiry") %>
<%= end_form_tag %>
Launch the built-in Webrick server & test the form:
C:\temp\EmailFormValidation> ruby script/server
Point your web browser to http://localhost:3000/contact

And Bob’s your uncle - The email form should now validate existence of data in the name & email fields and also validate the format of the email address using standard rails form validation.


This example application can be downloaded from: EmailFormValidation_RoR_Example.zip (77kb)

Labels: , , , , , , , ,


HenryL said...

I'm looking forward to trying your example.
I am a newbie and have had some trouble in running it.

I dumped the ZIP contents into my existing rails 1.2.2 directory (where another project exists at the same level as this example).

I edited 'databases.yml' to point to the existing database.

http://localhost:3000/contact gives the message;

no route found to match "/contact" with {:method=>:get}

Is there other plumbing that I've missed? Note that I didn't run 'rails' to make the root directory, but just put your zip archive contects there.


11:01 AM  
abhi said...

thanks! it is realy a very gud post simple as well as very effective thank u.

10:58 PM  

Post a Comment

<< Home