Rails allows you to define routes with named prefixes. I expected Rails to somehow know that I wanted my prefix to separate the rest of the name with an underscore.

Here was my original routes:

config/routes.rb

1 ActionController::Routing::Routes.draw do |map|
2 map.resources :parties, :path_prefix => "/admin" do |parties|
3 parties.resources :addresses,
4 :controller => "address_contact_routes",
5 :name_prefix => :party
6 end
7
8 map.resources :addresses,
9 :controller => "address_contact_routes"
10 end

Then, when I tried to use my route, I was getting a NoMethodError:


1 1) Error:
2 test_can_show(AddressContactRoutesControllerTest::PartyWithAddressTest):
3 ActionView::TemplateError: undefined method `party_address_path’ for #<#<Class:0xb768f6ac>:0xb63ee41c>
4 On line #3 of app/views/address_contact_routes/address_contact_route.rhtml
5
6 1: <%
7 2: if address_contact_route.routable && !address_contact_route.new_record? then
8 3: update_url = "#{party_address_path(address_contact_route.routable, address_contact_route)}.txt"
9 4: end
10 5: -%>
11 6: <% inline_fields_for(:address, address_contact_route, :url => update_url) do |f| -%>
12
13 #{RAILS_ROOT}/app/views/address_contact_routes/address_contact_route.rhtml:3:in `_run_rhtml_47app47views47address_contact_routes47_addresscontact
route46rhtml’

After a bit of sleuthing (and adding messages to ActionController::Routing::RouteSet#add_named_route), I found out that I was supposed to put the underscore myself on the prefix, like this:


1 map.resources :parties, :path_prefix => "/admin" do |parties|
2 parties.resources :addresses,
3 :controller => "address_contact_routes",
4 :name_prefix => :party_
5 end

It was also interesting to see all those generated routes. I discovered that the route with a format was named formatted_whatever.

Here’s a diff against the 1.2 branch of Rails that allows you to see all the generated routes as they are read:


1 $ svn diff vendor/rails/actionpack/lib/action_controller
2 Index: vendor/rails/actionpack/lib/action_controller/routing.rb
3 ===============
4 - vendor/rails/actionpack/lib/action_controller/routing.rb (revision 6424)
5 + vendor/rails/actionpack/lib/action_controller/routing.rb (working copy)
6 @ -349,7 +349,9 @
7
8 method_decl = "def generate_extras(#{args})\npath, hash = generate_raw(options, hash, expire_on)\n[path, extra_keys(options)]\nend"
9 instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})"
10 – raw_method
11 + returning raw_method do
12 + RAILS_DEFAULT_LOGGER.debug {raw_method}
13 + end
14 end
15
16 # Build several lines of code that extract values from the options hash. If any
17 @ -999,6 +1001,7 @
18 deprecate :root => "(as the the label for a named route) will become a shortcut for map.connect ’’, so find another name"
19
20 def method_missing(route_name, *args, &proc)
21 + RAILS_DEFAULT_LOGGER.debug {"ActionController::Routing::RouteSet::Mapper#method_missing(#{route_name.inspect}, #{args.inspect})"}
22 super unless args.length >= 1 && proc.nil?
23 set.add_named_route(route_name, *args) <span class="no">24</span> end <span class="no"><strong>25</strong></span> @ -1175,6 +1178,7 @@
26 end
27
28 def add_named_route(name, path, options = {})
29 + RAILS_DEFAULT_LOGGER.debug {"ActionController::Routing::RouteSet#add_named_route(#{name.inspect}, #{path.inspect}, #{options.inspect})"}
30 named_routes[name] = add_route(path, options)
31 end
32

For reference, here are all the generated routes for this declaration:

config/routes.rb

1 ActionController::Routing::Routes.draw do |map|
2 map.resources :layouts, :path_prefix => "/admin"
3 end

layouts =&gt; "/admin/layouts"
formatted_layouts =&gt; "/admin/layouts.:format"
new_layout =&gt; "/admin/layouts/new"
formatted_new_layout =&gt; "/admin/layouts/new.:format"
edit_layout =&gt; "/admin/layouts/:id;edit"
formatted_edit_layout =&gt; "/admin/layouts/:id.:format;edit"
layout =&gt; "/admin/layouts/:id"
formatted_layout =&gt; "/admin/layouts/:id.:format"

EDIT (2007-03-14 16:52 EDT): Changed link to routing.rb file to the Rails Trac Browser.

Over on Software Development Budoka, Berin Loritsch talks about supporting The Rel-Tag Microformat in Rails. Unfortunately, he uses a very obscure approach.

Here is his code:


1 class TagsController < ApplicationController
2 layout site
3
4 def method_missing(methodId)
5 name = methodId.id2name
6 tag</span> = name <span class="no"> 7</span> <span class="iv">tagged_items = Project.find_tagged_with :any => name
8 render tags\list
9 end
10 end

Unfortunately, that is very unclear. Much better to use routes to do the same thing:

config/routes.rb

1 ActionController::Routing::Routes.draw do |map|
2 map.connect tags/:tag_name,
3 :controller => tags, :action => by_tag
4 end

app/controllers/tags_controller.rb

1 class TagsController < ApplicationController
2 layout site
3
4 def by_tag
5 @tagged_items = Project.find_tagged_with(
6 :any => params[:tag_name])
7 render tags\list
8 end
9 end

In my mind, that seems to be the easiest way to do the job.

Search

Your Host

A picture of me

I am François Beausoleil, a Ruby on Rails and Scala developer. During the day, I work on Seevibes, a platform to measure social interactions related to TV shows. At night, I am interested many things. Read my biography.

Top Tags

Books I read and recommend

Links

Projects I work on

Projects I worked on