Understanding Pluralization Patterns in RailsProblemYou've noticed that Rails relies heavily on convention. In particular, it often uses pluralization to link the name of a database class to the corresponding model and controller classes. You want to understand where pluralization is used and where it isn't. SolutionThere are three main places in Rails where pluralization conventions are used by default:
Becoming familiar with these three conventions will go a long way toward getting comfortable with Rails. The intent of pluralization is to make your code more readable and transparent. For a good demonstration of how readable Rails code can be, look at the setup of a one-to-many relationship between chapters and recipes: app/models/chapter.rb: class Chapter < ActiveRecord::Base has_many :recipes end This code reads: "A chapter has many recipes." You can see how this goes a long way toward explaining the underlying relationship between chapters and recipes. It's clear enough to nonprogrammers or clients. There are other places where Rails uses pluralization, including view directory names, functional and unit test filenames, and test fixture filenames. One of the best ways to get used to pluralization is to experiment with Rails generators while using the --pretend option (or simply -p) when using script/generate to create scaffolding, controllers, or models. $ ruby script/generate scaffold -p recipe exists app/controllers/ exists app/helpers/ create app/views/recipes exists test/functional/ dependency model exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/recipe.rb create test/unit/recipe_test.rb create test/fixtures/recipes.yml create app/views/recipes/_form.rhtml create app/views/recipes/list.rhtml create app/views/recipes/show.rhtml create app/views/recipes/new.rhtml create app/views/recipes/edit.rhtml create app/controllers/recipes_controller.rb create test/functional/recipes_controller_test.rb create app/helpers/recipes_helper.rb create app/views/layouts/recipes.rhtml create public/stylesheets/scaffold.cs Rails prints out a dump of all the files it would create, based on the string you pass to it, but it doesn't actually do anything. You can use the --pretend flag to see how and when, Rails pluralizes various words. Lastly, Geoffrey Grosenbach has posted an online tool called The Pluralizer that demonstrates all of Rails' pluralization conventions for a given word. You can find the tool at http://nubyonrails.com/tools/pluralize. DiscussionPluralization in Rails is often a hot topic of debate, especially among skeptics who are hunting for fuel for an argument. Pluralization is just one of a number of conventions that Rails uses in an attempt to eliminate much of the configuration normally associated with web development frameworks. Ultimately, pluralization is just a convention. You can always disable it globally or override it in specific cases. You can turn it off by adding the following to the environment.rb configuration file: config/environment.rb: ActiveRecord::Base.pluralize_table_names = false One problem with pluralization is that not all the words get the correct inflection treatment. The class that decides how to pluralize words is called Inflections. This class defines methods that get mixed into Ruby's String class; these methods are made available to all String objects in Rails. You can experiment with these methods, namely pluralize, directly from the Rails console. For example: $ ruby script/console Loading development environment. >> "account".pluralize => "accounts" >> "people".pluralize => "peoples" Many of the various edge-cases of English pluralization are contained in a file called inflections.rb within the ActiveSupport gem directory. Here's an abbreviated version of that file: activesupport-1.3.1/lib/active_support/inflections.rb: Inflector.inflections do |inflect| inflect.plural(/$/, 's') inflect.plural(/s$/i, 's') inflect.plural(/(ax|test)is$/i, '\1es') ... inflect.singular(/s$/i, '') inflect.singular(/(n)ews$/i, '\1ews') inflect.singular(/([ti])a$/i, '\1um') ... inflect.irregular('person', 'people') inflect.irregular('man', 'men') inflect.irregular('child', 'children') ... inflect.uncountable(%w(equipment information rice money species series fish sheep)) end You may eventually find a specific pluralization rule that is not contained in this file. Let's say, for example, that you have a table containing foo records (each containing a tip aimed at helping newbies become Ruby masters). In this case, the pluralization of foo is just foo, which is not what the pluralize method expects it to be: $ ruby script/console >> "foo".pluralize => "foos" Rails calls words that are the same in both plural and singular form uncountable. To add the word foo to a list of all uncountable words, add the following to the bottom of environment.rb: config/environment.rb: ... Inflector.inflections do |inflect| inflect.uncountable "foo" end Reload script/console, pluralize foo again, and you'll find that your new inflection rule has been correctly applied. $ ruby script/console >> "foo".pluralize => "foo" Other inflection rules can be added to the block passed to Inflector.inflections. Here are a few examples: Inflector.inflections do |inflect| inflect.plural /^(ox)$/i, '\1\2en' inflect.singular /^(ox)en/i, '\1' inflect.irregular 'octopus', 'octopi' inflect.uncountable "equipment" end These rules are applied before the rules defined in inflections.rb. Because of this, you can override existing rules defined by the framework. See Also
|