Adding reCAPTCHA to Comments in Your Rails App

by Mike Zazaian at 2009-09-15 20:07:38 UTC in plugins rails gems

how to easily add reCAPTCHA confirmation to comments and other models in your Rails application using the ambethia-recaptcha gem

no comments 3 links

Spam, the great nuisance of the Internet, has met some modicum of resistance in recent years from CAPTCHAs, or visual confirmation tests that are more easily dispatched by humans than malicious bots. They're useful, they're effective, and as many such niceties in Rails, they're pretty durn easy to implement.

I've always been a fan of reCAPTCHA in particular, largely due to its delightful style, the fact that it uses whole words rather than arbitrary (and sometimes impossible-to-read) letters, and the ability to select a new challenge word on the fly, and the option to play challenge words as audio clips.

Indeed, reCAPTCHA helps to ensure that ONLY bots are blocked out, instead of just everyone on your site who isn't capable of deciphering abstract blobs of ink that are supposed to resemble letters and words.

getting started

Okay, before leaping in head-first, you're going to need a reCAPTCHA account. Luckily, you can sign up for one here. And it's free.

So -- first things first, you'll be asked to create a basic user account. Easy enough. Nothing to be scared of here.

Once you've done that you'll be prompted to enter the domain at which you're going to be using the secure keys with which it provides you, so do that. You also have the option (which is very useful) to just enable the key to work on all domains so if you have multiple sites you won't have to sign up for multiple accounts. Nifty.

Once you've done that you'll be shown a page with two keys -- one public, one private. HOLD ONTO THESE. You'll need them in a moment after we've got our Rails plugin set-up.

Speaking of which...

plug it in, plug it in

As you might imagine, due to our delightfully robust community of Rails developers, there's a plugin on github, ambethia-recaptcha, that makes it enormously easy to utilize reCAPTCHA on a site without doing too much heavy lifting.

If you want to install it as a basic plugin in your rails app, just navigate to the root directory of your Rails app, and type:

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

That'll do the job. If you're using git you can also install the plugin as a submodule, like this:

$ git submodule add http://github.com/ambethia/recaptcha/tree/master
 ./vendor/plugins/recaptcha

If you don't know how to use git submodules, or just want to read a really insightful and amazingly well-written article on them, you can do so here.

gem it in, gem it in

You can also install ambethia-recaptcha as a gem, which is my preferred weapon of choice due to the ease of updating and modularity that it affords (although the git submodule method also allows easy updating. oh well...).

Just make sure that you've got the github gem repository at http://gems.github.com installed as a source, before you do anything else:

$ gem sources list
*** CURRENT SOURCES ***

http://gems.rubyforge.org/

If you don't see it in there, then you can just:

$ sudo gem sources -a http://gems.github.com
$ gem sources list
*** CURRENT SOURCES ***

http://gems.rubyforge.org/
http://gems.github.com/

Yeesh that was tricky. And it's even more difficult to install:

$ sudo gem install --remote ambethia-recaptcha

Yeah, real tough. A wonder that anybody uses Rails at all.

There is one extra step, though, if you install ambethia-recaptcha as a gem, being a config.gem in your app's /config/environment.rb file. Just enter the following config.gem line in that file inside of the Rails::Initializer block, like this:

Rails::Initializer.run do |config|
...
  # Configure application for use with ambethia-recaptcha gem
  config.gem "ambethia-recaptcha", :lib => "recaptcha/rails", :source => "http://gems.github.com
...
end

Well done. You're good to go.

using those nifty keys

Take a look at your /config/environment.rb file. Trust me, you're going to want to go there.

As you'll see from the ambethia-recaptcha github page there are a couple of ways to enter your reCAPTCHA keys into your application. One entails actually entering the keys every time you access the reCAPTCHA API, which seems quite redundant, insecure, and not at all DRY (the ambethia-recaptcha page alludes to this issue as well).

You can also keep the keys in the ~/.profile file in your server's admin user's home directory, which works fine but is just one more thing to keep track of in the event of server migration, and could get messy if you have multiple apps running on the server using multiple reCAPTCHA keys.

So, in the interest of Occam and his Razor I took the simplest route and integrated the keys as environment variables in my...wait for it.../config/environment.rb file:

#!/config/environment.rb

ENV['RECAPTCHA_PUBLIC_KEY']  = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
ENV['RECAPTCHA_PRIVATE_KEY'] = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'

Obviously you should replace these bogus keys with the ones from your shiny new reCAPTCHA account. Go for it. Don't be scared. Ya done? Cool.

and the magic begins

So now, assuming that you've read everything that's led up to this point in the article, you should have everything in order and you're ready to use the ambethia-recaptcha gem. If you just jumped to this point in the article because you were eager to see some magic I appreciate your healthy enthusiasm, but strongly urge you to read everything else in the interest of saving yourself a lot of heartache and possibly some sort of manual injury that will likely result from the excessive table pounding you're about to engage in. Just a thought.

So you're here, and all is well with the world. And coincidentally, your Rails application uses comments on its posts/articles model, but you've been getting all kind of spam from bots and you're really already pretty happy with your penis size, and while you're flattered that you've been approached by nine separate Nigerian royal families for investment opportunities, your portfolio's all tied up in tech stocks right now and you're not feeling too bullish on the strength of the Nigerian naira at the moment.

Well, you're not alone, and reCAPTCHA was invented specifically for you (and, well, everybody else). But, luckily for you, it's dead-easy to implement:

#!/app/controllers/comments_controller.rb
class CommentsController < ApplicationController
...

  def create
    @article = Article.find params[:article_id]
    @comment = @article.comments.build(params[:comment])
    if verify_recaptcha(:model => @comment) && @comment.save
      redirect_to(article_path(@article) + "#comment_#{@comment.id}")
    else
      render :action => "new"
    end
  end

...
end

So that's just a basic idea of what your comments controller might look like. The really important line here is the one that begins with the verify_recaptcha method. Yeah, that's the biggie. It'll confirm whether or not the correct response was entered to the challenge prior to the comment being posted.

Also, by passing :model => @comment as an option, any errors that arise as a result of an invalid response will be tacked on to that @comment object, so that it doesn't pass validations prior to being saved. Neat, huh? You don't even have to use the flash. I thought that was a really nice touch.

There's also the :message option, which allows you to customize the message that the :model => @comment error will potentially spit out. It could look like this for example:

verify_recaptcha(:model => @comment, :message => "I declare, kind sir -- you have entered the reCAPTCHA code incorrectly.  Do try again!")

That of course would be the message you might use if your Rails app was geared toward 19th century British aristocrats. There's got to be a market for that, right?

the final countdown

The very last thing that you'll have to do is just to place the actual reCAPTCHA box in your articles or comments view, which you can do simply by calling recaptcha_tags from anywhere inside of your views. There are also options that the recaptcha_tags() method affords you in terms of styling the box itself, but the documentation for this was pretty dodgy, and I couldn't figure out how to implement it despite an otherwise valiant effort if I do say so myself. If anybody has any luck with the recaptcha_tags(:display => "theme: 'custom'") or any other theme options, please be so kind as to share your findings and success with the rest of the class.

the end

So that's all she wrote. Your comments model is now secure from the likes of spam-propagating brigands, and the kingdom that is your Rails app may ascend, unfettered, into greatness on the backs of its citizens (your users), and the delightful feedback and comments that they provide may bolster your great web civilization into the ranks of history's great societies.

I dub thee Sir reCAPTCHA, protector of innocent web forms.

no comments

post comment
Comments are marked down using Ryan Tomayko's excellent rdiscount gem, which follows standard markdown conventions. If you don't know markdown, you can learn it using the Daring Fireball markdown syntax guide.
required
required
login to post comments without entering your name, email address and recaptcha code each time, or register if you haven't already done so

markdown basics

**bold** __bold__ [link](http://link.com "link") * unordered list item
*italic* _italic_ ##h2 heading 1. ordered list item
> blockquote ####h4 heading <code>@ruby</code>

latest links

ActiveScaffold A Ruby on Rails plugin for dynamic, AJAX CRUD interfaces
rsl's stringex at master - GitHub Some [hopefully] useful extensions to Ruby’s String class. It is made up of three libraries: ActsAsUrl [permalink solution with better character translation], Unidecoder [Unicode to Ascii transliteration], and StringExtensions [miscellaneous helper methods for the String class].
friendly-id's friendly_id-2.1.4 Documentation

login

register activate reset

feeds

articles/rss

topics

staff

editor

about

doblock focuses on ruby, rails, and all things that can help ruby and/or rails programmers hone their skills.

Techniques, tutorials, news, and even free open-source applications, doblock seeks to fill in the cracks of the ruby/rails blogosphere.

doblock v. 0.8.22 powered by Rails