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

  map.resources :addresses,
      :controller => "address_contact_routes"
end
Then, when I tried to use my route, I was getting a NoMethodError:
1
2
3
4
5
6
7
8
9
10
11
12
13
  1) Error:
test_can_show(AddressContactRoutesControllerTest::PartyWithAddressTest):
ActionView::TemplateError: undefined method `party_address_path' for #<#<Class:0xb768f6ac>:0xb63ee41c>
    On line #3 of app/views/address_contact_routes/_address_contact_route.rhtml

    1: <%
    2:   if address_contact_route.routable && !address_contact_route.new_record? then
    3:     update_url = "#{party_address_path(address_contact_route.routable, address_contact_route)}.txt"
    4:   end
    5: -%>
    6: <% inline_fields_for(:address, address_contact_route, :url => update_url) do |f| -%>

    #{RAILS_ROOT}/app/views/address_contact_routes/_address_contact_route.rhtml:3:in `_run_rhtml_47app47views47address_contact_routes47_address_contact_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
2
3
4
5
map.resources :parties, :path_prefix => "/admin" do |parties|
  parties.resources :addresses,
      :controller => "address_contact_routes",
      :name_prefix => :party_
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ svn diff vendor/rails/actionpack/lib/action_controller
Index: vendor/rails/actionpack/lib/action_controller/routing.rb
===================================================================
--- vendor/rails/actionpack/lib/action_controller/routing.rb    (revision 6424)
+++ vendor/rails/actionpack/lib/action_controller/routing.rb    (working copy)
@@ -349,7 +349,9 @@

         method_decl = "def generate_extras(#{args})\npath, hash = generate_raw(options, hash, expire_on)\n[path, extra_keys(options)]\nend"
         instance_eval method_decl, "generated code (#{__FILE__}:#{__LINE__})"
-        raw_method
+        returning raw_method do
+          RAILS_DEFAULT_LOGGER.debug {raw_method}
+        end
       end

       # Build several lines of code that extract values from the options hash. If any
@@ -999,6 +1001,7 @@
         deprecate :root => "(as the the label for a named route) will become a shortcut for map.connect '', so find another name"

         def method_missing(route_name, *args, &proc)
+          RAILS_DEFAULT_LOGGER.debug {"ActionController::Routing::RouteSet::Mapper#method_missing(#{route_name.inspect}, #{args.inspect})"}
           super unless args.length >= 1 && proc.nil?
           @set.add_named_route(route_name, *args)
         end
@@ -1175,6 +1178,7 @@
       end

       def add_named_route(name, path, options = {})
+        RAILS_DEFAULT_LOGGER.debug {"ActionController::Routing::RouteSet#add_named_route(#{name.inspect}, #{path.inspect}, #{options.inspect})"}
         named_routes[name] = add_route(path, options)
       end
For reference, here are all the generated routes for this declaration:
1
2
3
ActionController::Routing::Routes.draw do |map|
  map.resources :layouts, :path_prefix => "/admin"
end
layouts => "/admin/layouts" 
formatted_layouts => "/admin/layouts.:format" 
new_layout => "/admin/layouts/new" 
formatted_new_layout => "/admin/layouts/new.:format" 
edit_layout => "/admin/layouts/:id;edit" 
formatted_edit_layout => "/admin/layouts/:id.:format;edit" 
layout => "/admin/layouts/:id" 
formatted_layout => "/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
2
3
4
5
6
7
8
9
10
class TagsController < ApplicationController
  layout 'site'

  def method_missing(methodId)
    name = methodId.id2name
    @tag = name
    @tagged_items = Project.find_tagged_with :any => name
    render 'tags\list'
  end
end
Unfortunately, that is very unclear. Much better to use routes to do the same thing:
1
2
3
4
ActionController::Routing::Routes.draw do |map|
  map.connect 'tags/:tag_name',
    :controller => 'tags', :action => 'by_tag'
end
1
2
3
4
5
6
7
8
9
class TagsController < ApplicationController
  layout 'site'

  def by_tag
    @tagged_items = Project.find_tagged_with(
      :any => params[:tag_name])
    render 'tags\list'
  end
end

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

 

Search

A picture of me

I am François Beausoleil, a Ruby on Rails coder. During the day, I work on XLsuite. At night, I am interested many things. Read my biography

Tags

(3) (1) (0) (2) (1) (1) (2) (2) (1) (2) (1) (2) (1) (2) (1) (1) (1) (1) (2) (14) (1) (1) (1) (1) (2) (1) (1) (2) (0) (1) (2) (1) (3) (1) (1) (1) (1) (1) (1) (0) (3) (2) (1) (2) (2) (1) (3) (2) (8) (8) (9) (12) (1) (1) (3) (1) (1) (1) (1) (1) (1) (2) (2) (2) (1) (1) (3) (1) (3) (1) (0) (23) (1) (1) (0) (1) (1) (1) (23) (25) (1) (1) (13) (1) (1) (2) (3) (1) (1) (4) (1) (2) (3) (0) (1) (7) (3) (1) (5) (5) (2) (2) (2) (4) (6) (7) (1) (0) (1) (1) (2) (2) (1) (4) (12) (2) (1) (2) (4) (1) (1) (1) (2) (8) (2) (3) (2) (2) (1) (3) (1) (1)

Links

Projects I work on

Categories

Archives