articles in April 2010

ActsAsTextcaptcha

1 comment

Announcing ActsAsTextcaptcha! It’s the first gem to be extracted from Bugle.

ActAsTextcaptcha

ActsAsTextcaptcha - pretending to be human just got tougher!

ActsAsTextcaptcha provides spam protection for your Rails models using logic questions from the excellent Text CAPTCHA web service (by Rob Tuley of Openknot).

To get started, grab an API key for your website and follow along with the instructions in the README.

You can also play around with a working demo on heroku.

The gem can be configured with your very own logic questions (to fall back on if the textcaptcha service is down) or as a replacement for the service. It also makes use of bcrypt encryption when storing the answers in your session (recommended if you’re using the default Rails CookieStore)

About the code

The gem contains two parts, a module for your ActiveRecord models, and a tiny helper method (spamify).

A call to spamify(@model) in your controller will query the Text CAPTCHA web service. A restful GET request is made with Net::HTTP and parsed using the standard XML::Parser. A spam_question is assigned to the model, and an array of possible answers are encrypted in the session.

validate_spam_answer() is called on @model.validate() and checks that the @model.spam_answer matches one of those possible answers in the session. This validation is only carried out on new records, i.e. never on edit, only on create. User’s attempted spam answers are not case-sensitive and have trailing/leading white-space removed.

BCrypt encryption is used to securely store the possible answers in your session. You must specify a valid bcrypt-salt and (computational) cost in your options. Without these options possible answers will be MD5-hashed only.

allowed?() and perform_spam_check?() are utility methods (that can be overridden in your model) They basically act as flags allowing you to control creation of new records, or whether the spam check should be carried out at all.

If an error occurs in loading or parsing the web service XML, ActsAsTextcaptcha will fall back to choose a random logic question defined in your options. Additionally, if you’d prefer not to use the service at all, you can omit the api_key from your options entirely.

If the web service fails or no-api key is specified AND no alternate questions are configured, the @model will not require spam checking and will pass as valid.

For more details on the code please check the documentation.

About the logic questions

Text CAPTCHA’s logic questions are aimed at a child’s age of 7, so they can be easily solved by all but the most cognitively impaired users. As they involve human logic, such questions cannot be solved by a robot. There are both advantages and disadvantages for using logic questions rather than image based captchas, find out more at Text CAPTCHA.Rob Tuley of Openknot

Finally, since things have changed so much over the years, i’ll be doing a refresher post on the state of play for creating/testing and releasing a Rails gem/plugin from scratch.

Rake Tasks

If you choose to install as a plugin, or are interested in the code, the following rake tasks are available;

  • rake spec (run the tests)
  • rake rcov (run tests showing coverage)
  • rake rdoc (generate docs)

Links

Who’s who?

Rails 3 preparation

no comments yet, post one now

Here’s a few links on Rails 3 I’ve collected in preparation for its release. I haven’t read these all through yet, or started using Rails 3 in any way, but I have a couple of production apps primed and waiting to be upgraded as soon as it launches.

Start with this one from RubyInside, 36 links to get you going

And finally some official release notes;

April 15, 2010 14:27

1955 BMW Isetta

no comments yet, post one now

I must have one! via CarType

April 15, 2010 14:00

The Tallest Man On Earth - King of Spain

no comments yet, post one now

April 03, 2010 19:07

Opinions matter

no comments yet, post one now

Be opinionated. In software its important. I’d go as far as saying it can completely make or break your app. It’s something that 37signals have been advocating for a long time, and something they practice daily in saying ‘No’. In fact in both Rework and Getting Real it is clearly stated that saying ‘No’ should be the default answer when considering any new feature (including their own!) I couldn’t agree more.

What happens when you don’t say no? It leads directly to feature bloat or in the long-term a big ball of mud. And if your business is beholden to clients who can throw financial weight around, then your’e really in trouble. You can end up second guessing their needs or prospecting new features that will attract them. This can be more true in b2b products where I think it can be much harder for people to say ‘No’ by default.

Apple take sides in a very obvious way. Rather than be all things to all people, they continually make game changing decisions that their competitors probably haven’t even considered. No DVD-drive in the Apple Air, loosing the conventional right-mouse button, more often than not they are constantly removing and simplifying their products. Look at everything thats not built into the iPad, you’ll find a long list of features if you compare against traditional touchpad devices.

All this creates division (and a buzz) amongst fans and critics. But have you ever heard an outcry over the latest updates to Microsoft Office? People just don’t care when an already bloated app tries to be all things to all people (and yes, I’m writing this post in Writeroom)

In building Bugle I have made lots of decisions along the way in code, the interface and even the server stack. Drawing on my own experiences and motivations has helped to keep things simple. Im not doing competitor comparisons or even looking at what people consider normal steps in the processes. I’m just defining the problems a user faces and trying to offer the simplest solution that will meet their needs.

Of course opinions matter in blog posts too, so what do you think, agree or disagree?

April 01, 2010 21:04
← (k) prev | next (j) →