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'
endActiveSupport::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