Contact Form in Rails
Hacking away as usual I found my self in need of a contact form. More precisely a form that sends an email, skipping any database fu. The first solution that came to my mind was to indeed create a new ActiveRecord model, and store inquiries in a database. The benefits are that it’s able to take advantage of ActiveRecord’s validations and filters (spam protection?). I went with ActionMailer over ActiveRecord because it meant less view code. Everyone loves a clean interface.
I love to share, so here’s my solution with some instruction.
The first step is to configure your Rails application with an email server. This site is hosted on a VPS, so consequently it’s running a custom mail server (one that I setup). For Slicehost people, and almost everyone else on a typical VPS setup, you can follow guides on creating a mail server here. For shared hosting people, look in your control panel or send a support request to get the required information. Open config/environment.rb and setup your mail server. You’ll want to add the mail server configuration at the very end of the file. It will look something like this:
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "mydomain.ca",
:port => 25,
:domain => "domain.ca"
}
Generate a new mailer, I called it “Notifications”, even though it will be used only for a “contact me” page. Just in case I decide to add a new comment notification system to my blog, I can use the same mailer.
$ script/generate mailer Notifications
Open up app/models/notifications.rb, it should look like this:
class Notifications < ActionMailer::Base
end
Now to add the method to handle a question.
class Notifications < ActionMailer::Base
def question(email_params, sent_at = Time.now)
subject "[MatHarvard.ca] " << email_params[:subject]
recipients "myemail@mydomain.ca" # Perhaps your address here?
from email_params[:address]
sent_on sent_at
# allows access to @message and @sender_name
# in the view
body :message => email_params[:body], :sender_name => email_params[:name]
end
end
email_params will be the data collected from the view (their name, message, email address etc.). Moving on to the email view. Open up app/views/notifications/question.erb and add:
<%= @sender_name %> wrote you an email:
---
<%= @message %>
---
This is just a plain text email, so nothing more is really needed. Feel free to change the format. Moving on to the controller and the form for our users to fill out.
$ script/generate controller contact
Now open app/controllers/contact_controller.rb and make it look similar to:
class ContactController < ApplicationController
def index
# render index.html.erb
end
def send_mail
Notifications.deliver_question(params[:email])
flash[:notice] = "Email was succesfully sent."
redirect_to :action => "index"
end
end
Now open app/views/contact/index.html.erb. This is only the form I used, it can be easily modified of course.
<% form_tag :action => "send_mail" do %>
<p>
<%= label_tag "email[name]", "Name" %><br />
<%= text_field :email, :name %>
</p>
<p>
<%= label_tag "email[address]", "Your Email Address" %><br />
<%= text_field :email, :address %>
</p>
<p>
<%= label_tag "email[subject]", "Subject" %><br />
<%= text_field :email, :subject %>
</p>
<p>
<%= label_tag "email[body]", "Your Message" %><br />
<%= text_area :email, :body, :rows => 8, :cols => 50 %>
</p>
<p>
<%= submit_tag "Submit" %>
</p>
<% end %>
Save all the files, start your application server, and go to domain.ca/contact. Facing you should be a not-to-fancy contact form. Try sending yourself an email to make sure everything works. Feel free to ask questions.


1 Comment
Ciaran · 25 days after on October 3rd, 2008
Thanks a lot, had a look through quite a few contact form tuts and yours was the most concise and to the point. Much appreciated !