This article is out of date and will soon redirect. Please see the latest version at https://richonrails.com/articles/adding-recaptcha-to-your-rails-application.

Introduction

For a site with lots of user generated content, fighting spammers can be a never ending battle. Luckily, we can use a service called reCAPTCHA to help keep spammers off our site. reCAPTCHA works by displaying an image on screen and asking the user to type what they see in the image. This works because, in theory, the spammer's spambots are unable to read the image and thus unable to proceed with filling out the form. reCAPTCHA is just one of a number of tools we can use to prevent spammers from abusing our websites.

Account Setup

First, we need to create a reCAPTCHA account. Visit the reCAPTCHA website and click the red button that says 'Use Recaptcha on Your Site'.

reCAPTCHA Example Screenshot 1

On the next screen click the 'sign up now' button.

reCAPTCHA Example Screenshot 2

On the next screen, enter your domain name and check the box that says 'Enable this key on all domains (global key)' then click the 'Create Key' button.

reCAPTCHA Example Screenshot 3

Make sure you copy the public key and private key and save it somewhere, you will need this information when adding reCAPTCHA to your Rails application.

Rails Application Setup

Now that we have an account, it's time to set up our Ruby on Rails application. The first thing we will need to do is include the recaptcha gem in our Gemfile. Add the following lines to your gemfile. Note that the bcrypt-ruby gem is used for our example user signup form. You don't have to include this in your application if you aren't using it for user authentication.

Gemfile:

gem 'recaptcha', '~> 0.3.5'
gem 'bcrypt-ruby', '~> 3.1.2'

Now run a bundle install to install the gem.

Terminal Commands:

bundle install

Now lets create an initializer for recaptcha that will contain the public and private keys we mentioned earlier. Create a new initializer called recaptcha.rb and add the code listed below, being sure to modify it to contain your public and private keys.

config/initializers.rb:

Recaptcha.configure do |config|
  config.public_key  = 'Replace with your public key'
  config.private_key = 'Replace with your private key'
end

Now, lets create a model called User that we will use to test the reCAPTCHA functionality. Run the following commands to create the user model.

Terminal Commands:

rails g model user name email password_digest
rake db:migrate

Next, open your User model and modify it so that it looks like the code listed below.

app/models/user.rb:

class User < ActiveRecord::Base
  has_secure_password
  validates_presence_of :password, on: :create
  validates :email, uniqueness: true, presence: true
end

Great, now lets create a couple controllers that will handle our user input. The first controller, Home, will provide a simple landing page that contains a sign up link. The second controller, Users, will process the actual user signup request. Run the commands below to create the controllers.

Terminal Commands:

rails g controller Home show
rails g controller Users new create

Now lets edit our routes file to set up a few routes for the controllers we just created. Modify the routes file so that it looks like the code listed below, being sure not to overwrite your application name on the first line.

config/routes.rb:

ReCAPTCHAExample::Application.routes.draw do
  resource :home, only: [:show], controller: :home
  resource :users, only: [:new, :create]
  root to: "home#show"
end

Great, now open up your home/show view and modify it so that it looks like the code listed below.

app/views/home/show.html.erb:

<h3>Welcome!</h3>
<p>
Click the link below to sign up for an account.
</p>
<%= link_to "Sign Up!", new_users_path %>

Great, now lets open up the users/new view and modify it so that it looks like the code listed below.

app/views/users/new.html.erb:

<h3>New User Sign Up</h3>
<% if [email protected]? %>
  <ul>
    <% @user.errors.full_messages.each do |message| %>
      <li><%= message %></li>
    <% end %>
  </ul>
<% end %>
<%= form_for User.new do |f| %>
<div>
  <%= f.label :name %>
  <%= f.text_field :name %>
</div>
<div>
  <%= f.label :email %>
  <%= f.text_field :email %>
</div>
<div>
  <%= f.label :password %>
  <%= f.password_field :password %>
</div>
<div>
  <%= f.label :password_confirmation %>
  <%= f.password_field :password_confirmation %>
</div>
<div>
  <%= recaptcha_tags %>
</div>
<div>
  <%= f.submit "Sign Up" %>
</div>
<% end %>

Most of the code is self explanatory, however, you'll notice the recaptcha_tagscode> method being called. This method is responsible for rendering the reCAPTCHA.

Now lets open up our users controller and add some code to handle the request. Modify your users controller so that it looks like the code listed below.

app/controllers/users_controller.rb:

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    captcha_message = "The data you entered for the CAPTCHA wasn't correct.  Please try again"
    @user = User.new(user_params)
    if !verify_recaptcha(model: @user, message: captcha_message) || [email protected]
      render "new"
    end
  end

private
  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end
end

Almost done! Now lets open up our users/create view and add the following code.

app/views/users/create.html.erb:

<h3>Thank You!</h3>
<p>
Thanks for signing up!
</p>

Now if you start a rails server and navigate to http://localhost:3000 we will see a sign up link. if you click on the sign up link you will be presented with a sign up form, complete with a captcha to fill out. You'll notice that filling out the captcha wrongly results in a validation error message, and filling out the correct information allows the user signup to proceed.

That's all there is to it! For more information, feel free to check out the reCAPTCHA Gem GitHub Page and thanks for reading!