named route not working -- input hash completely ignored

I have been reading that you can pass a parameters hash to a named route: <p>You can get <%= link_to "help!", assist_path(:action => "membership") %></p> <p>You can get <a href="/assistance/membership">help!</a></p>

Now, for me, I have the following named route:

# the bootcamp calendar map.bootcamp_calendar "/boot_camp_info/Calendar/:year/:month",       :controller => "boot_camp_info",       :action => "Calendar",       :requirements => {:year => /\d{4}/,:month => /\d{1,2}/},       :defaults => {:year => Date.today.year, :month => Date.today.month}

However, my code <p><%= link_to "Prev", bootcamp_calendar_path(:year => '2008', :month => '3') %></p>

Produces <a href="/boot_camp_info/Calendar">Prev</a> not <a href="/boot_camp_info/Calendar/2008/3">Prev</a>

In fact, when debugging, bootcamp_calendar_path(:year => '2008', :month => '3') resolves to /boot_camp_info/Calendar and neglects the hash values.

I have fought with this for awhile, but I am at a loss. I have traced all the rails code I can find, but don't see where things could be going wrong.

Any help greatly appreciated.

regards,

tim

Hi --

I have been reading that you can pass a parameters hash to a named route: <p>You can get <%= link_to "help!", assist_path(:action => "membership") %></p> <p>You can get <a href="/assistance/membership">help!</a></p>

Now, for me, I have the following named route:

# the bootcamp calendar map.bootcamp_calendar "/boot_camp_info/Calendar/:year/:month",      :controller => "boot_camp_info",      :action => "Calendar",

It's much better to use lowercase names for methods. Uppercase names are legal (and there are a few even built into Ruby), but they're very unidiomatic for controller actions (and most purposes).

     :requirements => {:year => /\d{4}/,:month => /\d{1,2}/},      :defaults => {:year => Date.today.year, :month => Date.today.month}

However, my code <p><%= link_to "Prev", bootcamp_calendar_path(:year => '2008', :month => '3') %></p>

Produces <a href="/boot_camp_info/Calendar">Prev</a> not <a href="/boot_camp_info/Calendar/2008/3">Prev</a>

There's no need for the defaults to be put explicitly in the path, because when you click on the version without them, they'll be interpolated anyway. It's an example of the fact that the routing system only makes sense to itself. When it produces a path string, it's producing a string that may not have a lot of human-readable info, but that will be understood (including interpolation of defaults) by the URL recognition process.

David

David,

Thank you so much for your reply. However, after reading your message several times, I am confused what you are recommending. Got it on the capitalization of the controller, put that in their early before I understood rails naming conventions. You don't think that is causing the problem, correct?

I am not trying to put defaults in the path -- I am trying to link to a specific month and year. I really need href="/boot_camp_info/Calendar/2008/3". With my named route, I would really like to get bootcamp_calendar_url(:year => @myyear, :month => @mymonth) to point to a specific year and month.

I have this working via a helper I made, I know I could even do:

<%= link_to "Next month", "#{bootcamp_calendar_path}/#{@myyear}/#{@mymonth}" %>

but after reading the documentation, I think bootcamp_calendar_path(:year => '2008', :month => '3') should work and I am really nervous that rails says it can do something that it doesn't do -- and no errors are returned. so i have things working, but I am worried that other things in rails might not be working as well. Do I have a legitimate bug here -- or am i doing something wrong?

best,

tim

David A. Black wrote:

Tim Booher wrote:

I am not trying to put defaults in the path -- I am trying to link to a specific month and year. I really need href="/boot_camp_info/Calendar/2008/3". With my named route, I would really like to get bootcamp_calendar_url(:year => @myyear, :month => @mymonth) to point to a specific year and month.

As David said, Rails doesn't need this because of your defaults. These mean that:

/boot_camp_info/Calendar

will be filled in with the default year and month, so if you try to create a link for the current year and month, Rails knows these are not required in the link so doesn't include them.

Rails uses all the information in your routes file to determine an appropriate URL for your request. Because you are specifying defaults, you are telling Rails that those values are optional, so Rails knows it can generate URLs without them and the result will be meaningful.

If the year and month must always be included in the URL, then don't supply defaults and always specify the values when creating your URLs.

Hi --

David,

Thank you so much for your reply. However, after reading your message several times, I am confused what you are recommending. Got it on the capitalization of the controller, put that in their early before I understood rails naming conventions. You don't think that is causing the problem, correct?

I am not trying to put defaults in the path -- I am trying to link to a specific month and year. I really need href="/boot_camp_info/Calendar/2008/3". With my named route, I would really like to get bootcamp_calendar_url(:year => @myyear, :month => @mymonth) to point to a specific year and month.

I have this working via a helper I made, I know I could even do:

<%= link_to "Next month", "#{bootcamp_calendar_path}/#{@myyear}/#{@mymonth}" %>

but after reading the documentation, I think bootcamp_calendar_path(:year => '2008', :month => '3') should work and I am really nervous that rails says it can do something that it doesn't do -- and no errors are returned. so i have things working, but I am worried that other things in rails might not be working as well. Do I have a legitimate bug here -- or am i doing something wrong?

Definitely not a bug. What you're not taking into account (and see Mark's answer too) is that the routing system talks to itself.

Given the defaults you've specified, when you click on this:

   "/boot_camp_info/calendar"

the routing system knows that you mean:

   controller: boot_camp_info    action: calendar    params[:year]: "2008"    params[:month]: "3"

That's what it means for there to be defaults. It doesn't mean that they get inserted physically into the path; it means that *without* having them physically present, the routing system knows that they're what you want.

The routing system uses your routing rule to:

   1. write the path string;    2. interpret a request URL that contains the path string.

Your rule specifies defaults; therefore, the system knows how to interpret a request that has no explicit values in the :year and :month positions. So that's what it writes, as the path, when it is asked to use the defaults.

David