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 !

Add Your Comment


(Never displayed.)

(Optional)

(URLs are auto-converted. HTML will be stripped.)

Navigation

Projects

Currently cooperating with Richard Neary on something that concerns audio.

A blog is typically published on a set date, and tagged with a few keywords. This is all that can be said.