A collection of computer systems and programming tips that you may find useful.
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Wednesday, June 30, 2010

Rails Routes and Models with 'Uncountable' Names

Rails follows the convention of using singular and plural forms of model names for various purposes. For example user.rb for a Model name and users_controller.rb for the controller.

Every once in a while you need a model where the singular and plural forms are the same. I just ran into that with a model called 'species'. This can cause you all sorts of hurt but here is a way round it.

First of all, decide if you really need to use that name. If you can figure out an equivalent where singular and plural forms are different then use it - much simpler... but if like me there is no good alternative then you do this:

1: Tell the built-in pluralization functions to skip your name.

In config/initializers/inflections.rb add this:
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w( species )
2: Create your model, controller, table etc in the normal way using 'species' as the model name.

3: In your routes.rb give the :species resource an artificial singular form:
ActionController::Routing::Routes.draw do |map|
map.resources :species, :singular => :species_instance

Doing this allows the routing magic to distinguish between singular and plural. But the downside is that you need to change a bunch of controller and view paths.

4: run 'rake routes' to see what Rails expects your new routes to look like.

5: In your controller, change any 'redirect_to @species' lines to 'redirect_to species_instance_path(@species)' (Should be just create and update actions).

6: In your index.html.erb view change:
link_to "Show", species
link_to "Show", species_instance_path(species)
In doing so you make it explicit that you want the singular form.
Similarly, change the following:
"Edit", edit_species_path(species)
"Edit", edit_species_instance_path(species)

link_to "Destroy", species ...
link_to "Destroy", species_instance_path(species) ...

and finally
link_to "New Species", new_species_path
link_to "New Species", new_species_instance_path

7: In your show, new and edit view pages, make similar changes. Links back to the index page can stay as 'species_path' but edit, delete and new links should be updated as shown above.

It's messy, for sure, but it solves the problem and allows you to retain 'natural' names in the user interface and in the URLs that users will see.


Archive of Tips