Routing for a Singleton Resource on Rails 2

While developing your RESTful Rails application, you use ActionController::Resources which magically generates a bunch of named routes to use in controllers and views.

For example, adding the following line to your config/routes.rb:

map.resources :products

gives you these paths: products_path, product_path(id), new_product_path and edit_product_path(id).

If your resource is a singleton one, you should simply do this:

map.resource :store

However, when you try to navigate to the edit action (/store/edit) you will get an error like this:

You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_sym

from the line that says <% form_for(@store) do |f| %> in your view.

I've discovered that there is already an open ticket for this issue. The problem is that Rails still assumes a collection resource. To fix this, you need to explicitly add the path to the form_for helper:

<% form_for(@store, :url => store_path) do |f| %>

Also, you will need to do the same in your update action:

redirect_to(store_path)

Now, if you are like me, you may try to use a singular name for your controller (StoreController). Now, you should get the next error:

uninitialized constant StoresController

Who mentioned StoresController?!

Well, Rails did! As documented here, the default controller name is still taken from the plural name.

To solve this, just add the controller name to your route:

map.resource :store, :controller => 'store'

Now, everything should work fine.

By the way, I have found a patch that allows scaffold generator to produce singleton resources: http://dev.rubyonrails.org/ticket/8832. But I didn't try it yet. Anyone did?

Did you like this article? Bookmark it:

Related Articles

Leave a Comment

If you want to post code, do this:
<pre><code class="ruby|javascript|css|html"> your code here </code></pre>