<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Wojno: Tag plural</title>
    <link>http://christopher.wojno.com/articles/tag/plural</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Exploration through Code</description>
    <item>
      <title>One-line Plurals</title>
      <description>&lt;h1&gt;Problems with Plurals&lt;/h1&gt;


	&lt;p&gt;Trevor brought up a good point in my last Rails &lt;a href="/articles/2007/08/06/easy-and-or-in-ruby-on-rails"&gt;post&lt;/a&gt; concerning plurals.&lt;/p&gt;


	&lt;p&gt;So I decided to enlighten him/create something new.&lt;/p&gt;


	&lt;p&gt;Rails offers a mixin for Action View called (oddly enough) &lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#M000618"&gt;pluralize.&lt;/a&gt;  It&amp;#8217;s fairly simple, but unnecessarily limited. Here&amp;#8217;s some syntax:&lt;/p&gt;


&lt;pre&gt;
&amp;gt;&amp;gt; pluralize(1, 'person')
=&amp;gt; 1 person
&amp;gt;&amp;gt; pluralize(3, 'person')
=&amp;gt; 3 people
&lt;/pre&gt;

	&lt;p&gt;It&amp;#8217;s annoying if you don&amp;#8217;t want the number or are trying to construct complicated sentences. The other big problem is that it doesn&amp;#8217;t work outside of an ActionView. Luckily, there&amp;#8217;s &lt;a href="http://api.rubyonrails.org/classes/Inflector.html#M001079"&gt;pluralize&lt;/a&gt; So I complied with Trevor&amp;#8217;s request but used the pluralize function:&lt;/p&gt;


&lt;pre&gt;
&amp;gt;&amp;gt; module SmartPlural
&amp;gt;&amp;gt; def plural( count=0 )
&amp;gt;&amp;gt; return ( count != 1 ? self.pluralize : self.dup )
&amp;gt;&amp;gt; end
&amp;gt;&amp;gt; end
=&amp;gt; nil
&amp;gt;&amp;gt; String.send :include, SmartPlural
=&amp;gt; String
&amp;gt;&amp;gt; "Trevor".plural( 3 )
=&amp;gt; "Trevors" 
&amp;gt;&amp;gt; "Trevor".plural( 1 )
=&amp;gt; "Trevor" 
&lt;/pre&gt;

	&lt;p&gt;Sorry for the lack of a ! (bang) version. That requires writing C-code&amp;#8230; and that means writing the pluralize function again&amp;#8230; and I&amp;#8217;m not doing that. Yes, you can call me lazy.&lt;/p&gt;


	&lt;h1&gt;What happened here?&lt;/h1&gt;


	&lt;p&gt;For those who are curious as to what I did: I created a module called SmartPlural, the name doesn&amp;#8217;t really matter. After that, I created a new function called &amp;#8220;plural&amp;#8221; 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 &lt;a href="http://whytheluckystiff.net/ruby/pickaxe/html/tut_modules.html#S2"&gt;mixin.&lt;/a&gt; Then I tested it on my friend here.&lt;/p&gt;


	&lt;h2&gt;Why didn&amp;#8217;t you do: (x.length == 1 ? &amp;#8216;foo&amp;#8217; : &amp;#8216;foos&amp;#8217;)&lt;/h2&gt;


	&lt;p&gt;Well, what if I don&amp;#8217;t like foos (bad Mr. T joke here, I won&amp;#8217;t suffer it upon you though)? Say I want to talk about octopus:&lt;/p&gt;


&lt;pre&gt;
&amp;gt;&amp;gt; 'octopus'.pluralize
=&amp;gt; "octopi" 
&lt;/pre&gt;

	&lt;p&gt;Rails already knows about quite a few irregular words and you don&amp;#8217;t want to pluralize &lt;ins&gt;every&lt;/ins&gt; word you&amp;#8217;ll be pluralizing yourself; that&amp;#8217;s just stupid and not &lt;acronym title="Don&amp;#8217;t Repeat Yourself"&gt;DRY&lt;/acronym&gt;. Use the pluralize function that comes with Rails. Here&amp;#8217;s yet another reason to do so. What if I like to &lt;a href="http://www.scifi.com/firefly/"&gt;juggle baby geese&lt;/a&gt;, you know, goslings? As in the previous example, octopus is a special word, it&amp;#8217;s plural isn&amp;#8217;t simply the original followed by an s. If I have:&lt;/p&gt;


&lt;pre&gt;
&amp;gt;&amp;gt; 'goose'.pluralize
=&amp;gt; "gooses" 
&lt;/pre&gt;

	&lt;p&gt;Rails is &lt;ins&gt;wrong&lt;/ins&gt;. It doesn&amp;#8217;t know about geese or goose. Now, I don&amp;#8217;t expect the Rails team to think of every word, and &lt;a href="http://api.rubyonrails.org/classes/Inflector/Inflections.html"&gt;neither did they.&lt;/a&gt; You can tell Rails how to plualize those special cases and it will be effective &lt;ins&gt;everywhere&lt;/ins&gt;, now that&amp;#8217;s &lt;acronym title="Don&amp;#8217;t Repeat Yourself"&gt;DRY&lt;/acronym&gt;.&lt;/p&gt;


&lt;pre&gt;
&amp;gt;&amp;gt; Inflector.inflections do |inflection|
&amp;gt;&amp;gt; inflection.irregular( 'goose', 'geese' )
&amp;gt;&amp;gt; end
=&amp;gt; [[/(g)eese$/i, "\\1oose"],... &amp;lt;snipped&amp;gt;
&amp;gt;&amp;gt; "goose".plural( 3 ) # make sure you have SmartPlural included in String
=&amp;gt; "geese" 
&lt;/pre&gt;

	&lt;h2&gt;Not all&lt;/h2&gt;


	&lt;p&gt;One more thing: the default value out of String.plural is, well, the plural form:&lt;/p&gt;


&lt;pre&gt;
&amp;gt;&amp;gt; "Trevor".plural
=&amp;gt; "Trevors" 
&lt;/pre&gt;

	&lt;p&gt;So if you&amp;#8217;re just interested in the plural form, and don&amp;#8217;t care about numbers, you don&amp;#8217;t have to use String.pluralize. Just a little bonus, a very small one.&lt;/p&gt;


	&lt;h1&gt;The One-Liner&lt;/h1&gt;


	&lt;p&gt;To use this code, just type (or preferably, paste):&lt;/p&gt;


&lt;pre style="overflow:auto;"&gt;
module SmartPlural; def plural(count=0); return (count != 1 ? self.pluralize : self.dup ); end; end; String.send :include, SmartPlural
&lt;/pre&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; I like apples&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Thu, 09 Aug 2007 14:30:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:53e8846b-b818-4fea-b0ec-4c4bc76a8a2f</guid>
      <author>Christopher Wojno</author>
      <link>http://christopher.wojno.com/articles/2007/08/09/one-line-plurals</link>
      <category>Rails Snippets</category>
      <category>rails</category>
      <category>plural</category>
      <category>one</category>
      <category>line</category>
    </item>
  </channel>
</rss>
