Ruby
Article

Quick Tip: Add ReCAPTCHA to Your Rails Application

By Kingsley Silas

This article was peer reviewed by Thom Parkin. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Keep out the robots!

ReCAPTCHA is a free service from Google that helps protect websites from spam and abuse. A “CAPTCHA” is a test to tell humans and robot apart. This kind of service is important for websites or web applications with lots of user generated content. The test is easy for a human to solve, but hard for bots and other malicious software to figure out.

In this tutorial, I will show you how to integrate ReCAPTCHA to your Rails application using ReCAPTCHA gem. You will also see how to add it to Devise.

Let’s get started!

ReCAPTCHA Setup

First, you need to obtain a ReCAPTCHA API Key. I presume that you have a Google account already, but if not, sign up for one.

recaptcha

On the ReCAPTCHA page, enter the details of your application and click Register. You will be presented with a page that contains your site key and secret key. Copy those to a safe location, it is wise to prevent these keys from being checked into source control.

Rails Application Setup

From your terminal generate a new rails application

rails new mypets

And bundle install

I chose Pets because I like dogs and I hope to get two soon :)

Let us generate a scaffold for our application:

 class='language-bash'rails g scaffold Pet name:string pets_type:string

Then migrate your database:

 class='language-bash'rake db:migrate

Integrating ReCAPTCHA

Add the following gems to your Gemfile and bundle install:

#Gemfile
gem 'dotenv-rails', :require => 'dotenv/rails-now'

gem "recaptcha", require: "recaptcha/rails"

Create a .env file in the root folder of your project and paste your ReCAPTCHA keys in there:

RECAPTCHA_PUBLIC_KEY = '<YOUR PUBLIC KEY>'
RECAPTCHA_PRIVATE_KEY = '<YOUR PRIVATE KEY>'

Save the file. Open .gitignore and add .env. This ensures your secret keys will not be part of the commit so they are not publicly visible in your git repo.

Configuring Views for ReCAPTCHA

First navigate to your controller and edit the create action to look like this:

#app/controllers/pets_controller.rb

def create
  @pet = Pet.new(pet_params)

  respond_to do |format|
    if verify_recaptcha(model: @pet) && @pet.save
      format.html { redirect_to @pet, notice: 'Pet was successfully created.' }
      format.json { render :show, status: :created, location: @pet }
    else
      format.html { render :new }
      format.json { render json: @pet.errors, status: :unprocessable_entity }
    end
  end
end

This will ensure that a new pet object is not created if ReCAPTCHA is not verified.

Let us move to the views.

Open app/views/pets/_form.html.erb and add a reCAPTCHA tag:

#app/views/pets/_form.html.erb

<%= form_for(@pet) do |f| %>
  <% if @pet.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@pet.errors.count, "error") %> prohibited this pet from being saved:</h2>

      <ul>
      <% @pet.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :pets_type %><br>
    <%= f.text_field :pets_type %>
  </div>
  <div>
    <%= recaptcha_tags %> <!-- THIS -->
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Start up the rails server (rails s) and point your browser to http://localhost:3000/pets/new to see reCAPTCHA at work.

ReCAPTCHA and Devise

Devise is a flexible authentication solution for Rails. In this part, I will show you how to integrate ReCAPTCHA with your Devise model.

Add devise to your Gemfile and bundle install.

# Gemfile
... other gems ...
gem `devise`

Install devise:

rails generate devise:install

Next let generate your User model:

rails generate devise User

Migrate your database

rake db:migrate

We will need to edit devise views so generate that too.

rails generate devise:views

Open your application layout using your text editor and paste this in, just below the body opening tag.

#app/views/layouts/application.html.erb

<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

Integrating ReCAPTCHA

For ReCAPTCHA to work, you will need to edit the create action in your controller like you did above. We’ll also need to make some changes in the Devise controllers.

Follow me.

Run this generator from your terminal:

rails generate devise:controllers users

This will create a controllers/users folder with all devise controllers contained in it.

Using your text editor, open app/controllers/users/registrations_controller.rb and edit the create action to look like this:

#app/controllers/users/registrations_controller.rb

def create
 if !verify_recaptcha
    flash.delete :recaptcha_error
    build_resource(sign_up_params)
    resource.valid?
    resource.errors.add(:base, "There was an error with the recaptcha code below. Please re-enter the code.")
    clean_up_passwords(resource)
    respond_with_navigational(resource) { render_with_scope :new }
  else
    flash.delete :recaptcha_error
    super
  end
end

Now navigate to app/views/devise/registrations/new.html.erb and add the ReCAPTCHA tag, so it looks like this:

#app/views/devise/registrations/new.html.erb

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= recaptcha_tags %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

Now with your browser pointed to http://localhost:3000/users/sign_up you will see ReCAPTCHA in action.

Conclusion

In this tutorial you have learned how to integrate ReCAPTCHA to your Rails application. I felt that adding the bits about Devise might be especially helpful, as it is such a popular gem. Try adding some ReCAPTCHA-based security to your app and let me know how it goes.

I like to write up quick-hitting topics like this one that can be applied immediately with tangible benefit. I hope you enjoyed it.

No Reader comments

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Ruby, once a week, for free.