Close and Go BackBack to Viget

Blocking Spam in Rails Applications

Ben Scofield
Ben Scofield, Development Director, November 01, 2006 0

Whenever you accept user-generated content, you run the risk of opening your system up to spammers. This is most well-known as a problem for blogs that allow comments; but, every relatively open site faces this challenge.

There are many potential solutions to this problem—you could write your own Bayesian filter, manually delete and blacklist IPs, or rely on an external service, for instance. For speed of development and ease of use, making use of an external service is by far the best way to go. For this post, we’re going to take a quick look at Akismet.

About Akismet


Akismet was developed by the good folks at Wordpress to deal with comment spam. It is a web service that uses a variety of strategies to classify submitted content as spam or not. It's easy to set up and is (in our experience) very reliable. A variety of key types are available, including both commerical and free.

Installation


The first step in getting Akismet working with your Rails app is to sign up for an API key (information on commerical keys can be found here). After getting your key, you'll need to download the Ruby API for Akismet and save it in your applications lib folder.

Catching Spam


Once you've got your key and the Akismet class installed, you're ready to start catching some spam. To use a consistent example for the rest of this post, let's say you're writing a blog application and you want to check for and prohibit spam in comments.

The most direct approach would be this:

class Comment
:create do |record, attr, value|
allow_comment = false
akismet = Akismet.new([YOUR API KEY], [THE URL FOR YOUR SITE])
unless akismet.verifyAPIKey
record.errors.add attr, 'could not be validated - your API key is incorrect'
else
allow_comment = akismet.commentCheck(
record.author.ip_address,
record.author.user_agent,
record.author.referrer,
record.post.permalink,
'comment',
record.author.full_name,
record.author.email,
record.author.url,
value,
{}
)
unless allow_comment
record.errors.add attr, 'appears to be spam'
end
end
allow_comment
end
end
Obviously, this code makes certain assumptions about data contained in the Post and Author models (namely, that a fair amount of environment data is stored in this comment's author object, and that the post to which this comment will be attached has some permalink method). Nevertheless, this is a quick and easy approach that works well and can be easily modified to fit other situations.
Trackback: SmickSmack / Some Cool/Interesting/Useful Ruby/Rails Stuff on 11/16 at 07:44 PM [...] My last two posts on Ruby on Rails both dealt with using external resources in your application (Akismet and the Yahoo Term Extractor, respectively). One difficulty that often arises when code relies upon external pieces is testing - third parties often frown on the high-volume, rapid hits that a comprehensive test suite generates, and test runs can be dramatically slowed when they rely on resources outside the local machine or network. Luckily, Rails has built-in support for a technique that resolves both of these difficulties: mock objects. [...]----- [...] Blocking Spam in Rails Applications [...]-----

Trackback URL: Trackbacks are disabled for this entry

A Development Community for Viget Labs and Beyond

Every team member here at Viget Labs strives to be an innovator. We members of the development team are no different - that's why we're constantly engaging in community discussions and exploring the unknown that is the next generation of open-source web applications.

Viget Is Hiring!

Viget has job openings for Ruby Developers, Interns, and Front-End Developers. Learn More »

Recent Comments

I have used several different strategies for achieving this, and have settled on the plugin seed_fu to accomplish this task. Because it uses plain ruby files you have quite a few more options for manipulating your seed data as opposed to using fixtures. I have found that this lets me create seed data that is much less brittle than fixtures can be. You can find seed_fu on...