Archive for the ‘Rails’ Category


Pluralization Helper for C#

In .Net,Rails on October 28, 2009 by Matt Grande Tagged: , , ,

UPDATE РThis code is now available on GitHub.  Click here for the repo.

I recently wanted a pluralization inflector in a C# project, one similar to the one in Ruby on Rails. Unable to find a satisfactory one, I whipped up my own. Here’s what I’ve got.

namespace MyNamespace
    public class Formatting
        private static readonly IList<string> Unpluralizables = new List<string>
        { "equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "deer" };
        private static readonly IDictionary<string, string> Pluralizations = new Dictionary<string, string>
            // Start with the rarest cases, and move to the most common
            { "person", "people" },
            { "ox", "oxen" },
            { "child", "children" },
            { "foot", "feet" },
            { "tooth", "teeth" },
            { "goose", "geese" },
            // And now the more standard rules.
            { "(.*)fe?", "$1ves" },         // ie, wolf, wife
            { "(.*)man$", "$1men" },
            { "(.+[aeiou]y)$", "$1s" },
            { "(.+[^aeiou])y$", "$1ies" },
            { "(.+z)$", "$1zes" },
            { "([m|l])ouse$", "$1ice" },
            { "(.+)(e|i)x$", @"$1ices"},    // ie, Matrix, Index
            { "(octop|vir)us$", "$1i"},
            { "(.+(s|x|sh|ch))$", @"$1es"},
            { "(.+)", @"$1s" }

        public static string Pluralize(int count, string singular)
            if (count == 1)
                return singular;

            if (Unpluralizables.Contains(singular))
                return singular;

            var plural = "";

            foreach (var pluralization in Pluralizations)
                if (Regex.IsMatch(singular, pluralization.Key))
                    plural = Regex.Replace(singular, pluralization.Key, pluralization.Value);

            return plural;

And of course, some NUnit tests.

namespace AutomatedTests
    public class FormattingTests
        public void StandardPluralizationTests()
            var dictionary = new Dictionary<string, string>();
            dictionary.Add("sausage", "sausages");  // Most words - Just add an 's'
            dictionary.Add("status", "statuses");   // Words that end in 's' - Add 'es'
            dictionary.Add("ax", "axes");           // Words that end in 'x' - Add 'es'
            dictionary.Add("octopus", "octopi");    // Some Words that end in 'us' - Replace 'us' with 'i'
            dictionary.Add("virus", "viri");        // Some Words that end in 'us' - Replace 'us' with 'i'
            dictionary.Add("crush", "crushes");     // Words that end in 'sh' - Add 'es'
            dictionary.Add("crutch", "crutches");   // Words that end in 'ch' - Add 'es'
            dictionary.Add("matrix", "matrices");   // Words that end in 'ix' - Replace with 'ices'
            dictionary.Add("index", "indices");     // Words that end in 'ex' - Replace with 'ices'
            dictionary.Add("mouse", "mice");        // Some Words that end in 'ouse' - Replace with 'ice'
            dictionary.Add("quiz", "quizzes");      // Words that end in 'z' - Add 'zes'
            dictionary.Add("mailman", "mailmen");   // Words that end in 'man' - Replace with 'men'
            dictionary.Add("man", "men");           // Words that end in 'man' - Replace with 'men'
            dictionary.Add("wolf", "wolves");       // Words that end in 'f' - Replace with 'ves'
            dictionary.Add("wife", "wives");        // Words that end in 'fe' - Replace with 'ves'
            dictionary.Add("day", "days");          // Words that end in '[vowel]y' - Replace with 'ys'
            dictionary.Add("sky", "skies");         // Words that end in '[consonant]y' - Replace with 'ies'

            foreach (var singular in dictionary.Keys)
                var plural = dictionary[singular];

                Assert.AreEqual(plural, Formatting.Pluralize(2, singular));
                Assert.AreEqual(singular, Formatting.Pluralize(1, singular));

        public void IrregularPluralizationTests()
            var dictionary = new Dictionary<string, string>();
            dictionary.Add("person", "people");
            dictionary.Add("child", "children");
            dictionary.Add("ox", "oxen");

            foreach (var singular in dictionary.Keys)
                var plural = dictionary[singular];

                Assert.AreEqual(plural, Formatting.Pluralize(2, singular));
                Assert.AreEqual(singular, Formatting.Pluralize(1, singular));

        public void NonPluralizingPluralizationTests()
            var nonPluralizingWords = new List<string> { "equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "deer" };

            foreach (var word in nonPluralizingWords)
                Assert.AreEqual(word, Formatting.Pluralize(2, word));
                Assert.AreEqual(word, Formatting.Pluralize(1, word));

And finally, usage.

var output = Formatting.Pluralization(2, "item");
// Produces "items"
output = Formatting.Pluralization(5, "sheep");
// Produces "sheep"
output = Formatting.Pluralization(100, "sausage");
// Produces "sausages"
output = Formatting.Pluralization(1, "sausage");
// Produces "sausage"

Now, I’m sure that I’m missing some cases in there. For example, I haven’t found a good way to pluralize “proof.” If any of you wonderful people find another missing case, or if you want to add one, let me know in the comments.


Love vs. Hate

In,Rails on October 1, 2009 by Matt Grande

So, I created a website. Maybe you’d like to visit it? It’s just a quick little thing. You can see it here:


Delaying File Processing & Uploading with DelayedJob and PaperClip

In delayedjob,paperclip,Rails,Ruby,s3 on August 11, 2009 by Matt Grande

I’m going to say it right now. I love DelayedJob. I’ve been working on a project that involves uploading assets, mostly images, to S3 and resizing the images to three sizes. With the addition of DelayedJob, this can happen much faster.

Before I go on, I should mention that I wouldn’t have been able to delay paperclip without this post, and I wouldn’t have been able to delay S3 uploads without this post. Thanks go out to both bloggers!

The original DelayedJob was done by tobi. I’ll be using the version created by collectiveidea, which has a few extra nice features.

So the first step is to install it. I had to install both the plugin and the gem. The plugin was unable to generate the database migration, and the gem was unable to run the rake task. Hopefully, it was either a mistake on my part, or they’ll fix it soon.

script/plugin install git://
sudo gem install collectiveidea-delayed_job

Collectiveidea’s delayed_job has a nice generation script which will make your delayed_jobs table for you.

script/generate delayed_job
rake db:migrate

You’ll also want to add a processing column to your asset table.

class AddProcessingToAsset < ActiveRecord::Migration
  def self.up
    add_column :assets, :processing, :boolean, :default => true

  def self.down
    remove_column :assets, :processing

Your next step is to move into the code. To prevent the S3 upload, we subclass our Asset model with TempAsset, and just save locally.

class TempAsset < Asset
  has_attached_file :media, :path => ":rails_root/tmp/uploads/:id/:basename.:extension"

In your controller, save your TempAsset instead of Asset, and call a method that will queue up the processing.

class AssetsController < ApplicationController
  def create
    @asset =;:asset&#93;)
    redirect_to @asset

From there, we want to make our <code>queue_move_to_s3</code> method.  I'm using <code>send_later</code> in this example, but <code>enqueue</code> works just as well.  While we're at it, we'll write the method that will perform the saving.

# In temp_asset.rb
def queue_move_to_s3

def perform
  asset = Asset.find( # This is the same db record as self =
  asset.processing = false!  # This will re-upload & re-size your image as per your has_attached_file method in Asset

  path =

One last thing you may want to do is have a “We’re Still Processing This File” image. Thanks to the processing column we added earlier, it’s a piece of cake.

# In asset.rb
def url(style=:thumb)
  if processing

There are unfortunately a few hoops to jump through to get this working, but in the end you have a much faster response time which leads to a much better user experience. Hope this helps!


Features I’m Currently Infatuated with in Rails

In Rails,Ruby on August 5, 2009 by Matt Grande

I’ve recently started a new project in Rails and I’m trying to follow all the best practices. Sometimes at my company they have fallen by the wayside, but I’m really putting an effort into enforcing them on the team. In doing so, I’ve started using a few methods that I’ve known about for awhile, but never really had a chance to use.

Nested Routes

In a blog, Post has_many Comments, that’s a given. Wouldn’t it be nice if your URLs reflected this relationship? Now they can! In your routes file, simply add map.resources :post, :has_many => [:comments]. Then, change your paths from new_comment_path to new_post_comment_path(@post). In your CommentsController, you’ll have access to both params[:id] and params[:post_id] now.

While we’re talking about related objects, rather than creating objects like this:

@post = Post.find(params[:post_id])
@comment =[:comment])
@comment.post_id =

Do something like this:

@post = Post.find(params[:post_id])
@comment =[:comment])

This way, your association is automatically built.

The new and improved render method

This has been in Rails for awhile now, but I’m just now getting a chance to use it. I always hated doing this:

<% @comments.each do |comment| %>
  <%= render :partial => "comments/comment", :locals => { :comment => comment } %>
<% end %>

It seemed so overly verbose, having the singular and plural form of ‘comment’ in there six times. As of Rails 2.2 (I believe) there’s been a handy helper, though.

<%= render @comments %>

The loops through all of your comments and renders them into the partial ‘comments/_comment.html.erb’ and give them a variable name of comment. But what do you do when you’re in the partial? Well that brings me to my next point…

The joy of div_for

You’re in a comment partial. You want to wrap the comment in a div with a unique id. You want to give all your comments the same class. Don’t do this:

<div id="comment_<%= -%>" class="comment">
  <!-- display the comment --></div>

when you can do this:

<% div_for(comment) do %>
  <!-- display the comment -->
<% end %>

Nice and easy.