Contact form in Rails 3
14, September 2012
The goal of this tutorial is to build a form that when submitted will validate and email the data.
To simplify this, I’m just using Google Apps to manage email addresses. If you have your own email server just modify the settings as needed. To get started you’ll need:
- A Google Apps account, of course
- Ruby on Rails 3.2.2 (give or take a few version numbers)
In an existing or new application, open config/application.rb
. Insert the following snippet in the Application
class.
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "yourdomain.dev",
:user_name => "from@yourdomain.dev",
:password => "Super-Secure-Password",
:authentication => :plain,
:enable_starttls_auto => true
}
config.action_mailer.default_url_options = {
:host => "yourdomain.dev"
}
Set the value of :domain
to the domain you’re using for Google Apps, and :user_name
and :password
to your Google Apps account credentials. In the second block replace :host
with the domain where the application is reachable from. The :host
option is used to ensure that all links in email templates generate full URLs.
To allow validation of the message, I create a model and just include ActiveModel
’s validations. Allowing the model to be written just like any other Rails model.
Create the file app/models/message.rb
, or with a name of your choice. Make the file look similar to the following.
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :subject, :body
validates :name, :email, :subject, :body, :presence => true
validates :email, :format => { :with => %r{.+@.+\..+} }, :allow_blank => true
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
This is fairly self explanatory. A message can have a subject and body, as well as the name and email address of the sender. All of the fields are required, and the email address is verified with a regular expression.
Run rails g mailer NotificationsMailer
. This generates app/mailers/notifications_mailer.rb
.
We’ll want notifications_mailer.rb
to look similar to this snippet. Check out the ActionMailer
API for specifics on what’s happening here.
class NotificationsMailer < ActionMailer::Base
default :from => "noreply@youdomain.dev"
default :to => "you@youremail.dev"
def new_message(message)
@message = message
mail(:subject => "[YourWebsite.tld] #{message.subject}")
end
end
Replace :to
, :from
and :subject
with the address you’d like the email sent to, the address it’s being sent from (should be the one you configured the Rails application with), and the subject of the email.
Create the file app/views/notifications_mailer/new_message.text.erb
.How the message looks is entirely up to you. Here’s an example of how it could be laid out.
Name: <%= @message.name %>
Email: <%= @message.email %>
Subject: <%= @message.subject %>
Body: <%= @message.body %>
Run rails g controller contact
and then open app/controllers/contact_controller.rb
.
The controller will only need two actions: new
and create
.
class ContactController < ApplicationController
def new
@message = Message.new
end
def create
@message = Message.new(params[:message])
if @message.valid?
NotificationsMailer.new_message(@message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
To get these actions working, open up config/routes.rb
and insert the following two lines.
match 'contact' => 'contact#new', :as => 'contact', :via => :get
match 'contact' => 'contact#create', :as => 'contact', :via => :post
When a GET
request is made to /contact
, the new
action is called. When a POST
request is made to /contact
, the create
action is called.
Create app/views/contact/new.html.erb
. As with the email template, this template is entirely up to you, I’m only providing an example of what it could look like.
<%= form_for @message, :url => contact_path do |form| %>
<fieldset>
<div>
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div>
<%= form.label :email %>
<%= form.text_field :email %>
</div>
<div>
<%= form.label :subject %>
<%= form.text_field :subject %>
</div>
<div>
<%= form.label :body %>
<%= form.text_area :body %>
</div>
</fieldset>
<fieldset>
<%= form.submit "Send" %>
</fieldset>
<% end %>
Start your rails server
and go to /contact
. Fill out the form and hit send. If everything was done correctly an email should arrive in the inbox of the address specified.