Using recaptcha in your Hobo Lifecycle

Posted by RitchieY.

The easiest way avoid having automated spam-bots creating zillions of fake accounts in your application is to put a captcha on the signup page. Recaptcha is a fantastically cool one because it:

  • Is a free service
  • Uses the responses to OCR books
  • Has an easy to use Rails plugin

This is how to add this functionality to a Hobo lifecycle event (create or transition). We’ll use the ‘signup’ create from the Agility tutorial as an example.

  • Install the recaptcha plugin:

     script/plugin install git://github.com/ambethia/recaptcha
  • Sign up to Recaptcha and generate the keys for your site.

  • Add the keys you’ve generated to your environment.rb:

     ENV['RECAPTCHA_PUBLIC_KEY'] = 'REPLACE-WITH-YOUR-PUBLIC-KEY'
     ENV['RECAPTCHA_PRIVATE_KEY'] = 'REPLACE-WITH-YOUR-PRIVATE-KEY'
  • In application.dryml extend the form tag for the lifecycle event that you’re protecting. For the signup create event, that would look like:

     <extend tag="signup-form" for="User">
       <old-signup-form merge>
         <after-field-list:>
           <%= recaptcha_tags %>
         </after-field-list:>
       </old-signup-form>
     </extend>

    The recaptcha_tags provides all the HTML needed to display the Recaptcha dialog. Here we’re adding it immediately after the other form fields. At this point you should be able to refresh the page and the Captcha should display. The result of the Captcha is ignored though. Nothing is protected.

  • In the controller for the model (eg users_controller.rb), add (or modify) the ‘do_’ method for the lifecycle action to verify the captcha prior to the actual hobo action being invoked. For signup, this should look something like this:

       def do_signup
        unless verify_recaptcha
           flash[:error] = "The Captcha words you entered weren't right."
           redirect_to :back
           return
         end
         hobo_do_signup
         end
       end

Try it out, your lifecycle event should now be protected by a Captcha.

You may have noticed that we didn’t really do anything lifecycle specific in here. You could use the same technique described to Captcha protect any form. I just chose lifecycles because they were a common case.

User contributed notes

  • On August 12, 2009 Bryan Larsen said:

    Just goes to show -- sometimes if one procrastinates long enough, somebody figures it out for you. Looks pretty simple. Thanks, Ritchie!
  • On August 20, 2009 GamaFranco said:

    5* :)
  • On September 11, 2009 Owen said:

    Kudos, Ritchie!
  • On December 08, 2009 Bryan Larsen said:

    Here's what I'm currently using for the verification block:

    unless verify_recaptcha
    self.this = User.new(params[:user])
    verify_recaptcha this
    render :action => :signup
    return
    end

    This mechanism ensures the user doesn't lose what he's already typed in. It also uses the ActiveRecord errors mechanism rather than a flash message.
  • On March 29, 2012 Bryan Larsen said:

    I can confirm that the recipe basically works on Rails 3 except that you add the plugin to the gemfile rather than using script/plugin install.
  • On March 29, 2012 Bryan Larsen said:

    Here's the do_signup I'm currently using. The first one I posted required create permission -- this one uses lifecycle permissions.
  • On March 29, 2012 Bryan Larsen said:

    def do_signup unless verify_recaptcha self.this = User::Lifecycle.creators[:signup].candidate(current_user, params[:user]) verify_recaptcha this render :action => :signup return end hobo_do_signup end