One-line Plurals
Posted by Christopher Wojno Thu, 09 Aug 2007 21:30:00 GMT
Problems with Plurals
Trevor brought up a good point in my last Rails post concerning plurals.
So I decided to enlighten him/create something new.
Rails offers a mixin for Action View called (oddly enough) pluralize. It’s fairly simple, but unnecessarily limited. Here’s some syntax:
>> pluralize(1, 'person') => 1 person >> pluralize(3, 'person') => 3 people
It’s annoying if you don’t want the number or are trying to construct complicated sentences. The other big problem is that it doesn’t work outside of an ActionView. Luckily, there’s pluralize So I complied with Trevor’s request but used the pluralize function:
>> module SmartPlural >> def plural( count=0 ) >> return ( count != 1 ? self.pluralize : self.dup ) >> end >> end => nil >> String.send :include, SmartPlural => String >> "Trevor".plural( 3 ) => "Trevors" >> "Trevor".plural( 1 ) => "Trevor"
Sorry for the lack of a ! (bang) version. That requires writing C-code… and that means writing the pluralize function again… and I’m not doing that. Yes, you can call me lazy.
What happened here?
For those who are curious as to what I did: I created a module called SmartPlural, the name doesn’t really matter. After that, I created a new function called “plural” that will pluralize the string if the number is not 1 (0 apples, 1 apple, 2 apples, etc.)[1]. Finally, I install the new module into the String class as a mixin. Then I tested it on my friend here.
Why didn’t you do: (x.length == 1 ? ‘foo’ : ‘foos’)
Well, what if I don’t like foos (bad Mr. T joke here, I won’t suffer it upon you though)? Say I want to talk about octopus:
>> 'octopus'.pluralize => "octopi"
Rails already knows about quite a few irregular words and you don’t want to pluralize every word you’ll be pluralizing yourself; that’s just stupid and not DRY. Use the pluralize function that comes with Rails. Here’s yet another reason to do so. What if I like to juggle baby geese, you know, goslings? As in the previous example, octopus is a special word, it’s plural isn’t simply the original followed by an s. If I have:
>> 'goose'.pluralize => "gooses"
Rails is wrong. It doesn’t know about geese or goose. Now, I don’t expect the Rails team to think of every word, and neither did they. You can tell Rails how to plualize those special cases and it will be effective everywhere, now that’s DRY.
>> Inflector.inflections do |inflection| >> inflection.irregular( 'goose', 'geese' ) >> end => [[/(g)eese$/i, "\\1oose"],... <snipped> >> "goose".plural( 3 ) # make sure you have SmartPlural included in String => "geese"
Not all
One more thing: the default value out of String.plural is, well, the plural form:
>> "Trevor".plural => "Trevors"
So if you’re just interested in the plural form, and don’t care about numbers, you don’t have to use String.pluralize. Just a little bonus, a very small one.
The One-Liner
To use this code, just type (or preferably, paste):
module SmartPlural; def plural(count=0); return (count != 1 ? self.pluralize : self.dup ); end; end; String.send :include, SmartPlural
1 I like apples…

Hey, who said I didn’t know about Rails’ pluralize method? Because I do. :P
It’s very useful when you’re actually using Rails. The problem is that you have to have to have ActiveSupport installed to use it outside of Rails. On the plus side, ActiveSupport full of good stuff anyway, so maybe that’s not so bad.
And ya, the ‘goose’/’gooses’ problem is annoying. Unfortunately, the irregularity of English makes it pretty hard to do this properly without referring to a dictionary of some sort. At least there’s the Pluralization Tester so one can at least find out what’s not going to work.