Announcing Fu-fu: The Profanity Filter for Rails

Posted by on June 6th, 2008.

That’s the most foul, cruel, and bad-tempered word you ever set eyes on!
Look, that word’s got a vicious streak a mile wide! It’s a killer!

There will be no killer words in this application: Behold the mighty Fu-fu! And there was much rejoicing… But first, a little history on Fu-fu: The Profanity Filter for Rails.

A Little History

Recently, I needed a simple (profanity/cuss/swear/bad word) filter for a Rails app, so I hit up Google for the answer as this seemed like a problem that should have been solved by an expert. Sadly, this was not the case.

Over the next day or so I was able to get a simple prototype up and running in our application and that’s the way it stayed for the next couple weeks. Then I realized that this was reason I wasn’t able to find a profanity filter plugin on Google.

Upon closer inspection it seems that people are building their own filters and leaving it at that. Almost being guilty of this, I decided that it was time to give back to the community and get a profanity filter plugin out in the wild.

I was able to publish the first version of the Profanity Filter during the Community Code Drive at RailsConf 2008. Hacking in the same room as DHH, David Chelimsky, Chad Fowler, Rich Kilmer, Marcel Molina Jr., and the entire Intridea team is a great motivator.

During RailsConf we decided that the plugin needed a real name; “Profanity Filter” wasn’t cutting it. Someone suggested fu-fu pronounced ‘eff-you-foo’. That was promptly shortened to ‘foo-foo’. How can you not love something named Fu-fu that deals with profanity and abuses plugin idioms at the same time?

Continue Rejoicing (Examples!)

The interface for Fu-fu is clean and straight forward. For example. lets say that ‘frak’ is a common curse word.

class Post < ActiveRecord::Base
  profanity_filter :title, :body
end

post = Post.create(:title => 'Fraking title', :body => 'What a bunch of frak')

post.title          #=> '@#$% title'
post.title_original #=> 'Fraking title'

post.body           #=> 'What a bunch of @#$%'
post.body_original  #=> 'What a bunch of frak'

By default the filter will replace common curses with the standard curse notation of ’@#$%’. Fu-fu is also has the ability to do dictionary replacements:

class Post < ActiveRecord::Base
  profanity_filter :title, :body, :method => 'dictionary'
end

post = Post.create(:title => 'Fraking title', :body => 'What a bunch of frak')

post.title          #=> 'fr*k*ng title'
post.body           #=> 'What a bunch of fr*k'

Fu-fu comes with a default dictionary file that replaces all vowels with asterisks (*).

You can also add an exclamation point to the end of the filter call (profanity_filter!) and have the method save the filtered text to the database (although this is not recommended for most applications).

You can also call Fu-fu directly:

ProfanityFilter::Base.clean('frak')               #=> '@#$%'
ProfanityFilter::Base.clean('frak', 'dictionary') #=> 'fr*k

Todos and Fixes

But alas, there is still danger in Caerbannog. As with all things, there is room for improvement.

* better filter regex, doesn't currently catch things like 'f-r-a-k'
* needs support for multiple dictionaries and configuration
* needs support for different levels of filtering (prude, normal, weak, etc)

Installation

To install the Fu-fu: The Profanity Filter on Edge Rails or Rails 2.1 and greater:

script/plugin install git://github.com/adambair/fu-fu.git

On earlier versions of Rails:

git clone git://github.com/adambair/fu-fu.git vendor/plugins/fu-fu

Resources

Bug tracking is available through the Fu-fu Lighthouse project. Also, feel free to contribute. I’ll be happy to accept patches and push requests for reasonable fixes and additions as long as they come with test coverage.

The source code is available on GitHub.

For general discussion about the plugin, please use the forums and wall of Fu-Fu’s Acts As Community Profile

Thanks to the Intridea team for their time, contributions, and suggestions. I’ve had a great time building Fu-fu and I hope someone may find it useful.

Share:

7 Responses to “Announcing Fu-fu: The Profanity Filter for Rails”

  1. leethal

    Hey that's a nice idea! +1 from the internet
  2. rafi

    Looking at the code, it works fine for small dictionaries, but you're iterating over the dictionary for every word in the input string. With a large dictionary, you'd need the use the dictionary as a tree in order to keep this from being an n-squared operation.
  3. Adam Bair (Intridea)

    rafi - After I saw your comment I went poking around and found that I was doing word lookups against an Array instead of a Hash (which was a mistake on my part). Hash lookups are waaay faster.

    I've provided some crude benchmarks for Fu-fu of which the results can be found in the Fu-fu github repo.

    I did benchmarks of different sized strings (100, 1000, 5000, 10000 words) and dictionaries (100, 1000, 5000, 25000, 50000, 100000 words) and found that the dictionary size didn't make that much of a different.

    10,000 word string 100 word dictionary:
    ( 0.059946) - single run

    10,000 word string 100,000 word dictionary:
    ( 0.055301) - single run

    I would think that most people would be using Fu-fu to filter out shorter strings like comments on a blog or in a forum with a basic dictionary. I could be wrong, but I think this is quite fast enough for that; besides, how many curse words can there be? :)

    (Disclaimer: I'm not an expert in benchmarking so please take my numbers with a grain of salt.)

  4. James Rosenstein

    Hey, You could also use the WebPurify Profanity Filter Service. I was able integrate it into my Rails App pretty easily. I went with a wed service because I found doing it myself was putting causing the load on my server to increase, plus they do some pretty intense checking for profanity.
  5. Cheri

    Hey, Can you add your own list of banned words? What if you want to replace the banned words with just a space. Is that possble with your plugin? Thanks, Cheri
  6. Adam Bair (Intridea)

    @James -- The service isn't a bad idea, it just depends on your application's specific needs.

    @Cheri -- You can certainly add your own set of banned words. The dictionary/substitutions can be found in the config/dictionary.yml. I've been meaning to add the ability for users to be able to specify their own dictionaries without having to deal with the one provided by default. I've created a ticket for this because of your suggestion:

    http://adambair.lighthouseapp.com/projects/12000-profanity-filter/tickets/10-allow-configurable-dictionary-files

    @Cheri -- You can also change the "@#$%" to a space although it require minor hacking right now. You can find this substitution on line #45 of lib/profanity_filter.rb. This should really be user configurable, just like the dictionary above. I've created a ticket for this as well:

    http://adambair.lighthouseapp.com/projects/12000-profanity-filter/tickets/11-allow-users-to-use-their-own-simple-substitution

    Thanks for the suggestions!

  7. Spencer Alexander

    Great idea! I've been considering implementing my own, hackish solution to the profanity problem (ie "this was reason I wasn’t able to find a profanity filter plugin on Google"), but it's great that you took the high route and made the plugin available to all!

Sorry, comments are closed for this article.