September 25, 2010

reCAPTCHA with Rails 3 without plugins

Filed under: Uncategorized — yasi8h @ 8:14 am

I needed to get some sort of a captcha solution up and running with the rails project that i am working on. Looked around and sure enough there is a easy solution. reCAPTCHA! its popular and its seems solid. there were some plugins for rails that would making integrating it a breeze too!. But oh well usually things aren’t that easy for me :P. Turns out all of the plugins that i came across don’t directly support rails 3. They are not either updated or maintained. See this is the problem with plugins. You got a ton of them for rails but rails updates so fast that most of the plugins are not up-to-date. Specially if its not one of the super star plugins. Anyways having plugins is good. Having ones that are not updated is much better than having none.

I could have got one of the available plugins and hacked it to work with rails. But me being lazy and all that. I figured i would just implement things my self, like reinventing the wheel 😉 Its pretty simple though. Heres how i did it.

BTW look here for a list of available plugins.

1. First of all head to and get your self registered. It should be straight forward. Obtain and remember your private and public keys.

2. Although i am not using a plugin i don’t want go against DRY completely. So add this piece of reusable code to your ApplicationController. In this set the RECAPTCHA_PRIVATE_KEY to your private key.

class ApplicationController < ActionController::Base


  #try and verify the captcha response. Then give out a message to flash
  def verify_recaptcha(remote_ip, params)

      responce = Net::HTTP.post_form(URI.parse(''),
                                    {'privatekey'=>RECAPTCHA_PRIVATE_KEY, 'remoteip'=>remote_ip, 'challenge'=>params[:recaptcha_challenge_field], 'response'=> params[:recaptcha_response_field]})
      result = {:status => responce.body.split("\n")[0], :error_code => responce.body.split("\n")[1]}

      if result[:error_code] == "incorrect-captcha-sol"
        flash[:alert] = "The CAPTCHA solution was incorrect. Please re-try"
        flash[:alert] = "There has been a unexpected error with the application. Please contact the administrator. error code: #{result[:error_code]}"


3. Add a new partial to views/share and name it as _recaptcha.erb (or as whatever template type you use). This will contain the stuff that goes in to a view where you wants to actually put the captcha in. For ex if you wants to use captcha where users are posting comments. You would render this partial in that view. Put the following code in to it. in this user your public key in place of PUBLIC_KEY.

<%= javascript_include_tag "" %>

	<iframe src="" height="300" width="500" frameborder="0"></iframe>
	<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
	<input type="hidden" name="recaptcha_response_field" value="manual_challenge">
<div id="captcha">
	<%= render '/share/recaptcha' %>

4. In the controller action that handles the post request for the comment creation (continuing the above example) you can use the following helper method to see if the user was able to solve the captcha accurately or not. If not you can get a error message and display that to the user or do something else.

# POST /comments
  # POST /comments.xml
  def create
    @comment =[:comment])

    if verify_recaptcha(request.remote_ip, params)[:status] == 'false'
      @notice = "captcha incorrect"
      respond_to do |format|
        format.html { render :action => "new" }
        format.xml  { render :xml => @comment.errors, :status => :unprocessable_entity }
      respond_to do |format|
          format.html { redirect_to(@comment, :notice => 'Comment was successfully created.') }
          format.xml  { render :xml => @comment, :status => :created, :location => @comment }
          format.html { render :action => "new" }
          format.xml  { render :xml => @comment.errors, :status => :unprocessable_entity }
5.  Thats it!. I did a example project while writing this post. You can get it from
Hope this helps.


  1. Thank you for this example, it works just fine!

    Comment by tehif — October 22, 2010 @ 3:34 pm

  2. thanks for the example !! That’s what I need.

    Comment by art — February 6, 2011 @ 10:20 pm

  3. Thank you so much for this simple and elegant solution, which worked for me immediately. You are right, there a gazillion plugins out there, but most of them just don’t work any more. I know, because I have lost 3 hours today in trying to fix one. I am all for do-it-yourself and usually also for DO-Repeat-Yourself, when the purpose merits it.

    Comment by Michael Franzl — November 3, 2012 @ 6:41 pm

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

%d bloggers like this: