This project is archived and is in readonly mode.

#1092 ✓invalid
Bill Burcham

setting "arbitrary" default value on route foils named route generation

Reported by Bill Burcham | September 22nd, 2008 @ 05:22 PM | in 2.x

Setting an "arbitrary" (i.e. not represented in the path) default value on a route (:name => value e.g. :layout => 'home') is described on pp 397-398 of the "Defining Routes with map.connect" section of chapter 20.2 "Routing Requests" of "Agile Web Development with Rails" second edition.

An "arbitrary" default value is one whose name does not appear as a tag in the path specification pattern. Here is an example (from routes.rb):

  map.home_index '', :controller => 'home',
    :extra_stuff => 'the_stuff'

This is useful for e.g. dynamically setting the layout based on the route:

  map.home_index '', :controller => 'home',
    :layout => 'home_layout'

And then using the value set in the route, to set the layout on a controller like so:

  layout proc{ |controller| controller.params[:layout]}

In Rails 2.1.0 this sort of route recognition works great. But when a route has "arbitrary" default values, route generation does not work (for that route). In order to get route generation to work for such a route, all the "arbitrary" default values must be specified to the generator. The problem is that these default values are not known and should not be known at the point of the generating call.

Here is a project that illustrates the issue:


rake test

And you'll see the failure. Important files are:

/config/routes.rb /test/functional/home_test.rb

The first test demonstrates the workaround (of explicitly specifying the "arbitrary" default values to the generate call) and the second test demonstrated the failure.

Comments and changes to this ticket

  • Pratik

    Pratik December 23rd, 2008 @ 12:52 PM

    • State changed from “new” to “invalid”

    You should be using :defaults might be helpful.


  • Bill Burcham

    Bill Burcham December 23rd, 2008 @ 05:27 PM

    • Assigned user set to “Pratik”

    Thank you for looking into this Pratik, however, you misunderstood the issue. Using :defaults doesn't help because the variable whose value I wish to set is not in the path (pattern).

    In my example the variable was named :extra_stuff. If I change my route to this as you suggest:

      map.home_index '', :controller => 'home',
        :defaults => {:extra_stuff => 'the_stuff'}

    And re-run my test:

      def test_index_no_explicit_extra_stuff
        # but URL generation fails if we leave it off
        assert_generates( '/', :controller => 'home', :action => 'index')

    I see this error now:

    /builder.rb:117:in `assign_route_options': extra_stuff: No matching segment exists; cannot assign default (ArgumentError)

    See "no matching segment exists". The whole point is that I wish to set a variable when a match happens. That variable is not part of the original path. The "Agile" book says this is possible (see reference above) and I've found it useful for e.g. setting the layout and for setting other static values that vary based on which routing rule fires.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>

People watching this ticket


Referenced by