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.
First, we need to create a reCAPTCHA account. Visit the reCAPTCHA website and click the red button that says 'Use Recaptcha on Your Site'.
On the next screen click the 'sign up now' button.
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.
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.
gem 'recaptcha', '~> 0.3.5' gem 'bcrypt-ruby', '~> 3.1.2'
Now run a bundle install to install the gem.
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.
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.
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.
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.
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.
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.
<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.
<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.
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.
<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!