Announcing the Badger Rails Plugin

Badger is a simple Rails plugin that creates photo badges. A site often allows its users to upload a profile image. A profile image is just that, an image resized to fit in a predefined space to show up in the user’s profile.

With Badger, you can have something prettier – a badge that shows the user- uploaded image on top of another image that identifies the user as a part of the community. We have company badges, security badges, so why not web badges to have your users show off his/her affection for your site?

Badger works by accepting cropping parameters of the overlay image in a hash (x1, y1, width, height), which is used to crop the overlay image. It then resizes the cropped image to the size specified by composite_width and composite_height in badger.yml. Finally, it places the resized image on top of the background image at location specified by composite_x and composite_y in badger.yml. The resulting image is saved back to either the filesystem or Amazon S3, using attachment_fu.

Badger requires the attachment_fu plugin, ImageMagick, and MiniMagick. Also, the JavaScript Image Cropper UI can be used to obtain the cropping parameters from the users.

Configuration

When this plugin is installed , the badger.yml will be copied to the config directory. You need to specify the following:

  1. background : filename of the background image, searching from public/images
  2. composite_x : top left corner of the overlay image location in x
  3. composite_y : top left corner of the overlay image location in y
  4. composite_width : width of the overlay image in pixels
  5. composite_height : height of the overlay image in pixels


For example, I want to overlay an image on top of a background image (badge.jpg). The box for the overlay image should be 30 pixels in width and 20 pixels in height, and it should appear at (x, y) = (60, 80) of the background image. My badger.yml then looks like:

  development:
    background: badge.jpg
    composite_x: 60
    composite_y: 80
    composite_width: 30
    composite_height: 20

Example

In the model that you use to store attachments:

  class Photo < ActiveRecord::Base
    has_attachment :content_type => :image,
                   :storage => :s3,
                   :max_size => 1.megabytes,
                   :resize_to => '320x200>',
                   :thumbnails => { :thumb => '100x100>' },
                   :processor => :MiniMagick
    validates_as_attachment
    has_badge :storage => :s3
  end

In the controller:

  def create_my_awesome_badge
    @photo = Photo.find(params[:id])
    # params[:crop_coord] is a hash with indexes x1, y1, width, height
    @photo.create_badge(params[:crop_coord])
  end

Improvements Needed

Please feel free to submit patches for bug fixes and improvements. Specifically, I would like to:

1. Use something nicer than system(“convert blah…”), but couldn’t get it to work. I don’t think Minimagick supports compositing images, so RMagick may have to be used, but is it worth the heavy memory consumption?

2. Make it more flexible (i.e. accept background image and composite params dynamically instead of in badger.yml). Maybe pass them in the call to create_badge?

Share:

Comment on this post (2 comments)


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:

Comment on this post (3 comments)


Improved BetterNestedSet Plugin

Posted by on October 27th, 2007.

On a recent project when I was using the BetterNestedSet plugin to manage a large hierarchal set of data, I encountered a problem that required me to find all of the items in a nested set that had children and those that didn't. In nested set terms I wanted: all 'parent' nodes and all 'leaf' nodes that exist within the 'tree'.

If you want to do this through the current BetterNestedSet interface you might be tempted to do something like this:


Continue reading this post

Share:

Comment on this post (1 comment)


Facebook Apps on Rails - Part 1

Posted by on September 20th, 2007.

At Intridea, we’ve been busy little beavers working on a couple of hush-hush facebook apps. Needless to say, you will be hearing about those quite soon. But first, a little discussion about Rails plugins for the Facebook F8 API is in order.

The most popular Rails plugin for the Facebook API is RFacebook. The core implementation of RFacebook relies a lot on Hpricot and method_missing (covered earlier in this post) to map the XML results from Facebook to Ruby objects.

There are a few goodies in RFacebook: SSH tunnelling, URL rewriting, and a nice debug panel that displays right on the facebook canvas. RFacebook is becoming more and more mature by the day, but unfortunately maturity sometimes does not equal usability or productivity (by Rails standards, of course). My main issue with RFacebook however, is the convoluted MVC design. For example, facebook session calls are made through a fbsession object. However, this object is accessible only within the controllers, and not the models. Moreover, fbsession objects use method_missing to transfer methods not defined in the ruby code over to Facebook, and so there is no concrete mapping between functions and their variables—it makes things like passing partials instead of strings as parameters for session calls in the controller more difficult, and lo and behold, we’re forced to use the ugliness that can only be mentioned as “html-code-in-the-controller”. Small things surely, but we use Rails and Ruby to “increase productivity and happiness”, and any libraries that have the possibility of being heavily used should be written with such things in mind.

A new contender is Facebooker written by Chad Fowler. He outlines the design points (most of which are vehement arguments against RFacebook’s way of doing things), in a very nice post. A quick look at the code (which is all I have done so far, more to come later) suggests that this is really a very concrete API, that maps functions to non-method_missing functions. However, it does have a bit of a learning curve right now and is well below RFacebook in terms of immediate user-friendliness, which is to be expected since it is still under development and has had no public announcement besides that blog post. More details as we move forward..

Running a quick search on ‘rails facebook plugins’ gives me more results today than it did a few weeks ago, so it seems apparent that there are a few more plugins left that I have missed. Along with that, the new release of Facebook’s Data Store will most definitely bring forth atleast a few more new ones.

Share:

Comment on this post (2 comments)