Skip to content

Contact Form using Mail_Form

Daniel Weller edited this page Jan 10, 2014 · 1 revision

This is a simple contact form that does not store data in a database. I will assume that you already have twitter bootstrap installed and have your mailer configured. If your mailer is not configured you can look at this post to set it up using local environment variables: Setting Up Mailer Using Devise For Forgot Password. It will also use a hidden field to check for computer's sending spam. I will also include styling of alert messages for bootstrap.

You will need to install gem 'mail_form' as well as the simple_form.

First we will create the route: “config/routes.rb” Your route should look like this:

resources "contacts", only: [:new, :create]

Next you will need to make a controller: “app/controllers/contacts_controller.rb” Within the contacts controller it should look like this:

class ContactsController < ApplicationController
  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(params[:contact])
    @contact.request = request
    if @contact.deliver
      flash.now[:notice] = 'Thank you for your message. We will contact you soon!'
    else
      flash.now[:error] = 'Cannot send message.'
      render :new
    end
  end
end

Next we will need a model: “app/models/contact.rb” Inside the model it should look something like this:

class Contact < MailForm::Base
  attribute :name,      :validate => true
  attribute :email,     :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
  attribute :message
  attribute :nickname,  :captcha  => true

  # Declare the e-mail headers. It accepts anything the mail method
  # in ActionMailer accepts.
  def headers
    {
      :subject => "My Contact Form",
      :to => "your_email@example.org",
      :from => %("#{name}" <#{email}>)
    }
  end
end

Make sure to enter the what you want the subject of the message to be when it is sent to you. You also need to tell the mailer where you would like to send the messages to.

Then we will need to create the views for the form. In “app/views/contacts/new.html.erb” you should put something like this:

<div align="center">
  <h3>Send A message to Us</h3>

  <%= simple_form_for @contact, :html => {:class => 'form-horizontal' } do |f| %>
    <%= f.input :name, :required => true %>
    <%= f.input :email, :required => true %>
    <%= f.input :message, :as => :text, :required => true %>
    <div class= "hidden">
      <%= f.input :nickname, :hint => 'Leave this field blank!' %>
    </div>
    <div>
      </br>
      <%= f.button :submit, 'Send message', :class=> "btn btn-primary" %>
    </div>
  <% end %>
</div>

The send message button will be from twitter bootstrap. The nickname attribute will be hidden so that no one can fill it out but computers will fill it out. This will determine whether the message is coming from a computer or not.

Next we can add styling for the alert messages. In the file “app/views/contacts/create.html.erb” you should add this to put the alerts into flash messages.

<div>
  <% flash.each do |key, value| %>
    <div>
      <a href="#" data-dismiss="alert">×</a>
        <%= value %>
    </div>
  <% end %>
</div>

You will also need to add some styling in the style sheets. In “app/assets/stylesheets/custom.css.scss” (or your stylesheet) you can add this to hide the nickname field we create earlier.

.hidden { display: none; }

In the same file you should add some styling for the flash notifications. I have set alert-error and alert-alert to be red to be used when things fail. I also have set alert-success and alert-notice to be green when things are successful.

/*flash*/

.alert-error {
background-color: #f2dede;
border-color: #eed3d7;
color: #b94a48;
text-align: left;
}

.alert-alert {
background-color: #f2dede;
border-color: #eed3d7;
color: #b94a48;
text-align: left;
}

.alert-success {
background-color: #dff0d8;
border-color: #d6e9c6;
color: #468847;
text-align: left;
}

.alert-notice {
background-color: #dff0d8;
border-color: #d6e9c6;
color: #468847;
text-align: left;
}