Ruby on Rails: pluralization

Anna Ol
3 min readApr 12, 2017

--

Using Rails we get access to lots of different features. One of them is pluralization. For making our word plural we need to call method #pluralize

2.3.0 :073 > "cat".pluralize=> "cats"

Or we can do like that:

2.3.0 :074 > helper.pluralize(12, "cat")=> "12 cats"

But if I change 12 to 1, method will return “1 cat”:

2.3.0 :001 > helper.pluralize(1, "cat")=> "1 cat"

That’s awesome! It seems that Rails “speaks” english and “knows” how to pluralize words.

But what about irregular or uncountable nouns? Ruby knows just some of them. For example:

2.3.0 :078 > "person".pluralize=> "people"

I tried fish, man, woman, mouse and some other nouns. But for instance Ruby can not properly pluralize “foot”, “tooth” or “hero”:

2.3.0 :076 > "foot".pluralize=> "foots"2.3.0 :077 > "tooth".pluralize=> "tooths"2.3.0 :078 > "hero".pluralize=> "heros"

What about some tricky stuff?

2.3.0 :079 > santa_reindeer = ["Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Dunder", "Blixem"]=> ["Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Dunder", "Blixem"]2.3.0 :080 > count_reindeer = 
"Santa has #{helper.pluralize(santa_reindeer.length, "reindeer")}!"
=> "Santa has 8 reindeers!"

Well, it seems Rails doesn’t speak English really well. But what should we do in this case? We can not let Santa has 8 reindeerS.

The answer is that I can add all additional rules into “Inflector” file in config/initializers/inflections.rb

If you open this file, you’ll see an example of the format:

# Be sure to restart your server when you modify this file.# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end

So in my case i should just add this code:

ActiveSupport::Inflector.inflections(:en) do |inflect|inflect.uncountable %w( reindeer )end

After restarting my server the result is:

2.3.0 :002 > count_reindeer = 
"Santa has #{helper.pluralize(santa_reindeer.length, "reindeer")}!"
=> "Santa has 8 reindeer!"

But what if you wanna make application with interface, let’s say, in Spanish or any other languages? How to teach Rails speak other languages?

For doing this I can localize inflections.

But why we can’t just add all the rules into one block without separating by languages?

For example, why we can’t do like that?

ActiveSupport::Inflector.inflections do |inflect|inflect.uncountable %w( reindeer sheep agua dinero )end

This is bad idea because there are different rules of pluralization In every language

For example: some of the words are spelling similar but pluralized differently:

Gen: english — gens, spanish— genes, dutch— gener , etc

For pluralization this word in other languages correctly, we need to create rule for each language (es — spanish, nl — dutch, etc)

ActiveSupport::Inflector.inflections(:es) do |inflect|
inflect.irregular 'gen', 'genes'
end
ActiveSupport::Inflector.inflections(:nl) do |inflect|
inflect.irregular 'gen', 'gener'
end

I didn’t create rule for english, because Rails already knows this word.

Now every time when we need to pluralize “gen”, i have to tell Rails what language rule to use. If we don’t mention language, Rails will use English rules like a default.

2.3.0 :001 > "gen".pluralize(:es)=> "genes"2.3.0 :002 > "gen".pluralize(:nl)=> "gener"2.3.0 :003 > "gen".pluralize=> "gens"

********

P.S.

Inflector gives us lots of additional helper methods for making interface more readable.

For example method Ordinalize :

2.3.0 :050 > array = ["Mike", "Jane", "Anna"]=> ["Mike", "Jane", "Anna"]2.3.0 :051 > array.each_with_index do |name, index|2.3.0 :052 >     index += 12.3.0 :053?>   puts "Hi, #{name}. You are #{index.ordinalize}"2.3.0 :054?>   endHi, Mike. You are 1stHi, Jane. You are 2ndHi, Anna. You are 3rd

--

--