Rails 4 Simple Form and Mail Form To Make Contact Form
In this tutorial I will be using the following gems:
- Rails 4
- mail_form 1.5
- simple_form 3
- Twitter Bootstrap
This tutorial will assume that you already have twitter bootstrap installed 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
I will show you how to set up a simple contact form which will not save anything into the database, use a hidden field to check against computers sending spam, and configure flash messages to make the form look even better!
Installing Gems
First you will need to add mail_form and simple_form into your “Gemfile”.
gem 'mail_form'
gem 'simple_form'
Then you can run bundle install to install the gems.
Creating the Contact Form
First we will create the route: “config/routes.rb” Your route should look like this:
match '/contacts', to: 'contacts#new', via: 'get'
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” 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; }
Now you have a working contact form. You can go to localhost:3000/contacts to see the form in action!
This tutorial was made using the following resources:
Tags: Contact Form, flash messages, Mail Form, Ruby on Rails, Simple Form, Twitter Bootstrap
Nice tutorial!
Everything work correctly, and also on my dev environment it looks perfect.
(on the terminal I see that my app send the mail).
But at the end I do not receive any ‘real’ mail on my email account (set on gmail).
For testing in the dev environment, and only there, I have to activate / deactivate some options somewhere?
Have you tried looking at this tutorial? https://rubyonrailshelp.wordpress.com/2014/01/02/setting-up-mailer-using-devise-for-forgot-password/
I get the same problem of not receiving the email at the end and can’t get it to work.
Anyone can explain more of the process?
Thanks!
Hi, I am having the same issue as tristelavoro. Would it be too much trouble to include the steps in this tutorial in order to receive real mail to the email address that we enter in our contacts model? Otherwise, this tutorial seems slightly incomplete.
What is the path to test? I tried localhost:3000/contacts and got a “No route matches [GET] “/contacts” ” error.
I went to localhost:3000/contacts/new and got this error:
============================================
undefined method `new’ for Contact:Module
Extracted source (around line #3):
class ContactsController < ApplicationController
def new
@contact = Contact.new
end
def create
Sorry I forgot to include that! You can add this line to the routes ” match ‘/contacts’, to: ‘contacts#new’, via: ‘get’ ” You can view it by going to localhost:3000/contacts -I will edit the page and add it in!
Thx, after doing that I get:
————————————————————
undefined method `new’ for Contact:Module
Extracted source (around line #3):
class ContactsController < ApplicationController
def new
@contact = Contact.new
end
def create
————————————————————-
I am too noob to figure this out on my own, what resources do you recommend for a C programmer to learn this?
@Jack I am not sure what is wrong. Did you try restarting the local server? You should also check the names for the files and make sure they are plural where necessary.
I would recommend this tutorial: http://ruby.railstutorial.org/ruby-on-rails-tutorial-book -Its one of the best resources and will help understand how rails works.
I am getting
Errno::ECONNREFUSED: Connection refused – connect(2)
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/smtp.rb:540:in `initialize’
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/smtp.rb:540:in `open’
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/smtp.rb:540:in `tcp_socket’
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/smtp.rb:550:in `block in do_start’
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/timeout.rb:66:in `timeout’
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/smtp.rb:549:in `do_start’
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/smtp.rb:519:in `start’
from /Library/Ruby/Gems/2.0.0/gems/mail-2.5.4/lib/mail/network/delivery_methods/smtp.rb:112:in `deliver!’
from /Library/Ruby/Gems/2.0.0/gems/mail-2.5.4/lib/mail/message.rb:2129:in `do_delivery’
from /Library/Ruby/Gems/2.0.0/gems/mail-2.5.4/lib/mail/message.rb:232:in `block in deliver’
from /Library/Ruby/Gems/2.0.0/gems/actionmailer-4.0.3/lib/action_mailer/base.rb:456:in `block in deliver_mail’
from /Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.3/lib/active_support/notifications.rb:159:in `block in instrument’
from /Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.3/lib/active_support/notifications/instrumenter.rb:20:in `instrument’
from /Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.3/lib/active_support/notifications.rb:159:in `instrument’
from /Library/Ruby/Gems/2.0.0/gems/actionmailer-4.0.3/lib/action_mailer/base.rb:454:in `deliver_mail’
from /Library/Ruby/Gems/2.0.0/gems/mail-2.5.4/lib/mail/message.rb:232:in `deliver’
from /Library/Ruby/Gems/2.0.0/gems/mail_form-1.5.0/lib/mail_form/delivery.rb:151:in `deliver!’
from /Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.3/lib/active_support/callbacks.rb:386:in `_run__92463961908501673__deliver__callbacks’
from /Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.3/lib/active_support/callbacks.rb:80:in `run_callbacks’
from /Library/Ruby/Gems/2.0.0/gems/mail_form-1.5.0/lib/mail_form/shim.rb:49:in `deliver’
from (irb):3
from /Library/Ruby/Gems/2.0.0/gems/railties-4.0.3/lib/rails/commands/console.rb:90:in `start’
from /Library/Ruby/Gems/2.0.0/gems/railties-4.0.3/lib/rails/commands/console.rb:9:in `start’
from /Library/Ruby/Gems/2.0.0/gems/railties-4.0.3/lib/rails/commands.rb:62:in `’
from bin/rails:4:in `require’
from bin/rails:4:in `’irb(main):004:0>
I had the same problem as Jack. It ended up being a typo in one of the filenames. I was trying to use “contacts_conroller.rb” instead of “contacts_controller.rb”
Any idea why I would be getting undefined method request= for Contact?
Hello! This post could not be written any better! Reading this post reminds me of my previous room mate! He always kept talking about this. I will forward this page to him. Pretty sure he will have a good read. Many thanks for sharing!
If error `undefined method `contact_path’ for` add
match ‘/contacts’, to: ‘contacts#new’, via: ‘get’, :as => :contact
How would I go about to make all of this work at URL ‘/contact’ (instead of ‘/contacts’)?
I tried to change all the occurrences of the string “contacts” into “contact”, i.e.
-3 times in ‘config/routes.rb’
-moved app/controllers/contacts_controller.rb to app/controllers/contact_controller.rb and changed the first line therein to read “class ContactController < ApplicationController"
-moved the views from 'app/views/contacts/ 'to 'app/views/contact/'
but I end up with an error: "No route matches [POST] "/contacts""
I got error, i work well
NoMethodError (undefined method `new’ for Contact:Module):
app/controllers/contacts_controller.rb:3:in `new’
I Added mandrillapp to my SMTP. Some time email not received
Thanks a lot ! It works like a charm !
Here is my route.rb for using localhost:3000/contact_us
get ‘contact_us’ => ‘contacts#new’, as:”contact”
resources ‘contacts’, only: [:create]
Hope this helps.
Greetings! This is a wonderful tutorial. It was very easy to follow and implement. However, I am receiving the following error in development:
Net::SMTPAuthenticationError in ContactsController#create
530-5.5.1 Authentication Required. Learn more at
Extracted source (around line #9):
7 @contact = Contact.new(params[:contact])
8 @contact.request = request
9 if @contact.deliver
10 flash.now[:notice] = ‘Thank you for your message. We will contact you soon!’
11 else
12 flash.now[:error] = ‘Cannot send message.’
app/controllers/contacts_controller.rb:9:in `create’
Is this an issue with devise?
I have checked my .env file, and everything there is correct. Please advise.
can’t receive real mail
This was an awesome post. Much appreciated.