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
    end

    def self.down
    remove_column :posts, :ham_comments_count
    end
    end



  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
    acts_as_snook
    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? %>
    < %= comment.author %>
    < % else %>
    < %= link_to comment.author, 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.



Conclusion


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....

Tuesday, May 5, 2009

Upcoming update to Theme support plugin

I'm updating the theme support plugin to work with 2.3.2 now. jystewart has done a tonne of work with it, but his plugin doesn't yet use the helpers, which my version does.


We'll either combine forks or go our separate ways depending on how things play out, so stay tuned!!!


Here is the theme support repo on github. Follow the fork link to jystewart's if interested.


UPDATE - Use jystewart's github theme support for 2.3.2 and mine for 2.2.2 rails app

For some stupid reason the core guys flip flopped on a code insertion that screwed up 2.2.2 and I had to fix it so that the helpers worked in rails 2.2.2.

However, now that they reverted to code from 2.1.2 in 2.3.2, the old helper methods, which the jystewart version didn't touch, work fine. So rather then mess with it, it's easier just to use jystwart's version.

Lastly, in rails 3.0 i think it will revert again, so stay tuned.

Friday, May 1, 2009

When in doubt... Factory it out...

Boy did i have a doozy of a day trying to get some basic tests to pass, after i added some validations to a basic rspec_scaffold. Using the barebones tests, adding the validates_presence_of and a validates_uniqueness_of both borked the test... which was fine, i expected that.


What i didn't expect was that when i commented out both validations, my create test spec method would still work. in essence, it didn't. It could have been something i did, whatever. I fixed the failing tests by simply switching to Factories, instead of fixtures, or whatever the base rspec scaffold would use in a model test.


If you are getting some weird errors, simply try to use factories instead. Try out Factory Girl by Thoughtbot for an example of one that I can say works. haven't tried too hard to get machinist to work yet, but heard good things too.

Saturday, April 25, 2009

Rails Template FTW

Boy oh boy, rails templates kick ass. I just made a template that has everything i need to start an user authenticated monthly subscription rspec app.


What's this template got that i ain't got?


Other then charisma and a good sense of style, it has


  • Restful_authentication w/ AASM && will_paginate - creates your User and Session automatically
  • Active_Merchant - sets you up for adding monthly subscription code
  • Subdomain_fu - allows for easy account creation with subdomains.
  • Testing: Rspec, Cucumber, machinist, faker, factory_girl too
  • rspec scaffold an account model to begin your journey


Rails templates are good to get you going but they are just a starting point, you still need to add certain bits of code to make stuff work, like
require 'aasm'
to your config/environment.rb file.


How to Rock the Template


Type the following into your console
rails -m http://github.com/nerbie69/rails-templates/restful_merchant_account.rb app_name_here -d postgresql
Remember that the code above will create a postgres based rails app, so supply whatever DB flag you want, mysql, couchdb etc, and replace app_name_here with whatever you want to call you app.

Wednesday, April 15, 2009

Rails Visionaries - Gems/Plugins Top Contributors

The following is a list of the people/companies whom i feel are leading the pack when it comes to the most useful gems and/or plugins. My criteria is that the gem/plugins are almost KEY to any rails app that needs them, and that this person/company has more then ONE key gem/plugin. FYI - I left out DHH, he gets enough accolades. Let's begin



  1. Technoweenie github repo - Where would a lot of rails apps be without restful_authentication and attachment_fu, just to start. When you add in Acts_as_paranoid and his work with Mephisto, we owe this dude a big thanks for making components of what we do in rails easier and more efficient.

  2. thoughtbot github repo - This company keeps pumping out hit after plugin/gem hit. In the field of testing, they help simplify our testing needs by putting out shoulda and factory girl. In the authentication field, they gave us clearance and paperclip. In the error notification field, they offer hoptoad, (which is rad).

  3. mbleigh github repo - Now mbleigh is a dude that should get mad props, and you should get to know his work, if you aren't familiar yet with him. Essential gems/plugins such as subdomain_fu and twitter_auth are just two of his current 24 projects he has on his repo. When you add acts_as_taggable_on and his ubercool uberkit (for easier form and menu creation), you realize how truly original his work is to our community.

  4. Phusion github repo - Passenger makes all production app serving easier. Back in the day, it was mongrel that made things easier... things keep evolving. However, i can't see how it could get any easier beyond Passenger, which makes setting up your slice/VPS extremely easy. And from their website they describe the Ruby Enterprise Edition as Transparently improve scalability and efficiency of Ruby on Rails web applications.

  5. Shopify github repo - If you handle anything to do with ecommerce you must bow at the generosity of the shopify folks. You have active_merchant, active_fulfillment and active_shipping. easy enough to use, powerful and well thoughtout and maintained.


Honourable Mention


There is no question to the visionary impact that these individuals have made to the rails community and furthering it's progress. In the spirit of this post however, these luminaries have given us fantastic testing apps, while this post was looking at those who have given us more then just one type of gem/plugin.



  • aslakhellesoy github repo - Cucumber is making BDD testing easier for everyone. A killer gem that makes learning testing palatable.

  • dchelimsky github repo - RSpec. enough said. (I do realize it is a team of core dev's who create this, but for clarity purposes, his name is usually at the forfront of any rspec conversation).

  • thinking_sphinx github and acts_as_ferret github - Good search plugins and gems. You are either a Ferret guy or a Sphinx guy.


Well that is the list. Enjoy

Tuesday, April 14, 2009

Struggles with webrat via cucumber

I know that this will end up being pebkac... but it still is annoying


So i have a problem. webrat is not acting how i thought it was supposed to. Ryan Bate's railscast on cucumber made this shit look so easy. And for the most part, it is.

However, when you go beyond what he had in his railscast - beginning cucumber, webrat takes me off the rails very fast.


to the Code...


all i wanted to do was select my choice from a dropdown menu. According to webrat/cucumber webrat_steps.rb file it should be
I select "option" from "field"


So in my scenario, i used the field name "tweet[style_id]" and the option "story".
I select "story" from "tweet[style-id]"
You may be wondering what that tweet[ ] business is all about, well that was the only way my scenario would go green, is if i used the label name in that style of code. Since i am not using a symbol in my
f.label :body, "I want to show this text" if you were simply using f.label :body, you wouldn't need the tweet[ ] syntax.


Updates

i did find this ruby forum post, however he simply had the wrong description text. Since my text is one word, and i copied and pasted from the view source code, i don't think that is my problemo. Maybe i should try using the label field without the quotes?

Friday, April 3, 2009

Weekend Rails Challenge #1

Thanks for participating in the first ever Weekend Rails Challenge.


The rules are simple for this challenge:
You have 48 hours to code a "For-Profit" based rails app using the twitter api. Also your app must have a colour scheme revolving around the following hex code #7C6D8A. Lastly you app Must be online and useable, hosted by yourself of course on your vps slice or node.
The challenge will run for a month and a winner will be chosen based on the app which gains the best combined score based on five different criterion.


Judging the winner



The winning app will have demonstrated the best TOTAL score of the following criteria:


  • (20%) Quality of Code - Following the rails mantra of DRY and readability, a mark will be given to you based on how well your code follows these coding principles. Usually you would test along the way but we've decided that in 48 hours that is not mandatory for this challenge.

  • (20%) Site Popularity - The site with the highest Alexa ranking at the end of the month will receive a full 20 points, 18 for the second best rank, down to 12 for the worst ranked site. 5 bonus points are rewarded for a mention in twitters sidebar menu (located below the profile of a twitter user)

  • (10%) Site Look and (10%) User Interface/Interaction - The site with the best looking and most functional user interface will gain top points in this category. Places 2nd, 3rd, and 4th will recieve 2 points less then the preceding ranking

  • (20%) Revenue made in a month - The site with the most revenue made during the month will gain top points in this category. Places 2nd, 3rd, and 4th will recieve 2 points less then the preceding ranking.

  • (20%) Most Creative Use of the given rules - An app that demonstrates the most creative and functional use of the given rules will gain top points in this category. Places 2nd, 3rd, and 4th will recieve 2 points less then the preceding ranking.




How will the scores be judged?


No idea, but i know that we participants will vote and we'll ask someone or a few people from ROR to vote on things like coding, site look and feel and creativity.


Submission Deadline:


We'll report back who ends up in the final challenge eventually, but if you want to enter, you MUST post a comment below regarding the purpose or solution you came up with for your app by 12 noon, as of you own time zone, on Saturday April 4th.



Good Luck Challengers


Best of luck and hey who knows... you could get a great money making app out of it. At worst, you made some new friendships and had a good weekend coding and learning.