reCAPTCHA on Rails

Posted on March 08, 2009

This has probably been done to death, but for the sake of Random Google Searches (RGSs), here is a quick run through about how to do reCAPTCHA with Rails.

First off, you need to register at recaptcha.net. Then you need to add your domain and get two keys (one public, one private). I created two sites once registered, one for my development environment (localhost), and one for production.

Second, there is a Rails plugin. It’s on GitHub. So install it like this:

$ ./script/plugin install git://github.com/ambethia/recaptcha.git

Third, take those public and private reCAPTCHA keys and place those suckers in your environment.rb or appropriate environment file. Here’s what I added to the bottom of my development.rb, replacing the ‘MY_PUBLIC_KEY’ and ‘MY_PRIVATE_KEY’ with the keys from recaptcha.net (but keep the single quotes):


ENV['RECAPTCHA_PUBLIC_KEY'] = 'MY_PUBLIC_KEY'
ENV['RECAPTCHA_PRIVATE_KEY'] = 'MY_PRIVATE_KEY'

Fourth, find the place in your views where you want the reCAPTCHA box to appear. The plugin defines a special view helper named recaptcha_tags. Here’s a basic example:

Ask a Question -- Get an Answer!

<% form_for(@question) do |f| %>
Question: <%= f.text_field :question %>
Human Test: <%= recaptcha_tags %>
<%= f.submit "Ask Question" %>
<% end %>

And here’s what it that basic html looks like:

Each page load will embed code that pings the reCAPTCHA API and generates a new captcha. Note that there are some extra options on recaptcha_tags if you need to handle ssl or want to by default not use javascript (uses an iframe instead).

Lastly, we have to handle the verification in the controller. Here’s how I integrated it:


def create
@question = Question.new(params[:question])
if verify_recaptcha() and @question.save
redirect_to :action => 'show', :permalink => @question.permalink
else
render :action => 'new'
end
end

The verify_recaptcha() method will take params from the POST request, ping recaptcha.net, and then return true or false. Then you can handle it however you want (here in the same block as model validation). If the captcha fails, it’ll render the new page again, where a small error message will show up in the reCAPTCHA box.

And that’s about it. Hat tip to Rob Olson for implementing this originally on Elevator Pitches (I checked out that implementation first).

Trackbacks

Trackbacks are closed.

Comments

Comments are closed.

  1. valk Sat, 11 Apr 2009 20:51:50 UTC

    Sorry, I think the line should be:
    ./script/plugin install git://github.com/ambethia/recaptcha.git
    instead of,
    ./script/install plugin git://github.com/ambethia/recaptcha.git

    Thanks alot!

  2. Henry Work Sat, 11 Apr 2009 20:55:30 UTC

    Thanks, valk! Fixed.

  3. calebhc Thu, 19 Nov 2009 14:40:46 UTC

    Thanks, this was very helpful!

  4. curious Tue, 05 Jan 2010 17:05:24 UTC

    What about making this work with tests?

  5. manmohan Fri, 12 Mar 2010 08:48:01 UTC

    i dont know why but plugin link is not working …. it is reporting me plugin not found …. i have even tried the new url from main site …. but same error

    i followed gem installation and it is working but again it gives error of it being depreciated …

    thank you

  6. manmohan Fri, 12 Mar 2010 08:49:22 UTC

    sorry!! gem intallation method does not give error but gives warning

  7. Sam Sun, 22 Aug 2010 10:38:11 UTC

    @manmohan my suggestion: make sure you’ve got git installed and operational, otherwise you’ll spend like 6 hours failing at plugin installation

  8. Eduardo Sun, 29 Aug 2010 17:48:39 UTC

    I need two recaptcha validations at the same page. reCAPTCHA is not working for me, just the first one is loaded. Could someone confirm it ?

  9. Van der Hoorn Tue, 26 Oct 2010 02:12:37 UTC

    There is an HTML-bug on line 25 of client_helper.rb. It says &error= but when linking to URIs the & should be escaped, so it should be &error=

    Also notice that setting flash[:recaptcha_error] = nil (verify.rb line 36) always renders the flash.

    Also, if you add errors to the model, you probably don’t want to render the flash (either you want the flash, or are using error_messages_for, but most certainly not both).

  10. Van der Hoorn Tue, 26 Oct 2010 02:13:46 UTC

    This blog escaped the &, so “&error=” should be “& amp ; error=” (without spaces)