Chronicling my experiences with ruby on rails, web application development/management.

Monday, May 18, 2009

Spam Off - Acts_as_Snook Tutorial

You wrote an awesome blog post. You've enabled comments for this awesome blog post, only to find that some crappy spam turnkey operation has hit your post with 1000 cialis ads, and the other wang pill advertisements.

Listen, Comment Spam sucks ass. If you've ever searched for an answer to stopping it, your research points you to one of four ways to stop comment spam traditionally. These are:

  • No comment spam filters at all - Users are allowed to comment willy nilly.

  • Captchas - weird images that look as though your seeing through beer goggles, whose text usually has to be written into a text field to prove your comment is coming from a human.

  • Site Members can comment only - the site's membership, of which you are visiting, are only allowed to comment on stories. I am using that method in my blog, atm.

  • Moderated comments - your honest feedback about a post can only be posted, if a nameless/faceless drone 'approves' your comment worthy of being posted. Doesn't say much for transparency.

While all of these above methods work to keep spam to a minimum, (and really that's all you can hope for i.e., minimal spam), there are glaring flaws in each and everyone one of the above methods. Whether it's accessibility, too cumbersome to keep up with, or too communist, most of these methods have some kind of tradeoff.

Enter Acts_as_snook

From the README:ActsAsSnook is a simple and elegant method of handling comment spam that doesn’t rely on CAPTCHAS or Javascript or external web services. It uses a point based system to detect common traits of comment spam.

The acts_as_snook plugin is a great way to keep spam at a minimum. Rather then asking the user to do anything, acts_as_snook "scores" each comment based on a scoring system by Jonathon Snook. Once the comment has been saved into the database, the comment receives one of three possible spam statuses:

  • Spam - the comment didn't pass the scoring system and will have a status of spam, set in the database.

  • Ham - the comment passes the scoring system and it's status is set to ham in the db.

  • Moderate - the comment is too close to call spam or ham, so it's status is set to moderate and is awaiting moderation.

About the Plugin

If anyone trolls in #rubyonrails, the IRC chatroom, you'll know the author of the acts_as_snook plugin, rsl.

He is also responsible for getting this song in my head, at the time of writing. Bastard.

Tutorial - How to use the Plugin

Don't cut and paste!!! this stupid blogger crap is garbage! So if you want to cut and paste, you'll need to delete the spaces after and before each < or > bracket.

Assumptions - you know how to create a typical blog application that will use embedded comments at the end of each post. I'm assuming that you will have two models Post andComment. Before you begin, get a working Post model ready, as this tutorial is only about adding a Comment model that uses acts_as_snook. Lastly, you'll want to make it prettier once your done these steps, so that is up to you do after, post modem.

  1. You have a working Post model, right???

    Get your Post model working how you want it to work. The inner workings aren't important for this tutorial.

  2. Generate a Comments Model and a Post Migration

    We'll use the default settings in acts_as_snook, so that means we need our database to house these Comments table columns as outlined below.

    script/generate rspec_scaffold Comment author:string email:string url:string body:text spam_status:string post_id:integer

    Since we want to display how many GOOD comments we have (i.e, the ham), acts_as_snook will run a counter cache for each Post's ham comments. All you have to create the following migration file and add the migration column information to it:

    script/generate migration AddHamCountToPost

    In your new migration file add the following:

    class AddHamCountToPost < ActiveRecord::Migration
    def self.up
    add_column :posts, :ham_comments_count, :integer, :default => 0

    def self.down
    remove_column :posts, :ham_comments_count

  3. Run Migration with
    rake db:migrate

  4. Add Acts_as_Snook functionality

    First make sure Post has_many Comments and Comments belongs_to Post.

    Next add this to your Comment.rb file
    Damn, that was easy.

  5. Fix the Comment views

    Right now, your views are set to show all comments, that is not good. Let's make your views shine! So in your Post#show view, here is what i've done (since i show my comments at the end of each blog post, my @comments= @post.comments. If you don't understand that, read up on associations in the rails guide). I'll explain the code further afterwards.

    < h1 >Comments< / h1 >
    < % unless @comments.blank? %>
    < % @comments.ham.each do |comment| %>
    < p >
    < % if comment.url.blank? %>
    < %= %>
    < % else %>
    < %= link_to, comment.url %>
    < % end %>
    says:< br/ >
    < %= comment.body %>< /p>
    < % end %>
    < % else %>
    < p>Be the first person to comment!< /p>
    < % end %>

    Simply put, we only want to show the ham(the good comments) and not the spam(shitty comments). So we iterate through each ham comment, using the acts_as_snook supplied method ham.

    The rest of this code, just shows the comment in a certain way that i wanted it to appear, your mileage will vary.

  6. Showing a Comment Count

    One last little touch, is showing your readers how many comments each post has. I put this information on the Post#index page, usually. Here's one way you can implement a count for all ham comments.
    < % @posts.each do |post| % >
    < h2 >< %= link_to post.title, post % > ::~ < %= pluralize post.ham_comments_count, "Comment" % >< /h2 >
    < p >< %= truncate post.body, 25 % >< /p >
    < % end % >

    Notice again, we iterate through the posts and for each post, we add their ham_comments_count.


Acts_as_snook gives us a lot of easy to use methods, which i'll write more about in Acts_as_Snook part 2, which will include a moderation area for administrators. Hopefully Acts_as_snook will take care of your comment spam nightmares, while giving you more time to sing, same as it ever was. Letting the days go by....

No comments:

Post a Comment