[Rails 3] Path helper not working as expected with form_for

Hi there,

I can’t seem to get form_for to work correctly with the URL I’m providing for a set of nested resources. Here’s what I’m doing in routes.rb:

resources :threads do

resources :messages


And then I’ve got the following form that I’m building as part of /threads/1/messages/1/edit. Both @thread and @message are set by the controller

<%= form_for @thread, :as => :thread, :url => thread_messages_path(@thread, @message) do |f| %>

<%= fields_for :message do |m| %>


<% end %>

<%= submit_tag "Update Message" %>

<% end %>

This is producing the following HTML:

Notice that while the HTTP method is correctly PUT, the form action ends in .1 instead of /1, which is confusing the router.

Curiously, the ‘new’ case seems to be getting properly constructed, though I had to manually specify the :method to properly generate the URL:

<%= form_for @thread, :as => :thread, :url => thread_messages_path, :html => {:method => :post} do |f| %>

<%= fields_for :message do |m| %>


<% end %>

<%= submit_tag "Create Reply" %>

<% end %>

Am I doing something obviously wrong or is this a deficiency in the path convenience methods? Note that I am using “:as =>” all over the place because the name of my model object (which is actually “Axthread”) does not cleanly map to a named route, and using “thread” as a model name is not an option.


So it would seem that there is huge level of subtly in how these path helpers behave based on how your pluralize the helper. So, what I should have written (and what now appears to work) was:

<%= form_for @thread, :as => :thread, :url => thread_message_path(@thread, @message) do |f| %>

So that’s thread_message_path, not thread_messages_path.

However, despite trying other options, it seems I still have to specify the HTTP verb as part of the ‘new’ case:

<%= form_for @thread, :as => :thread, :url => thread_messages_path(@thread), :html => {:method => :post} do |f| %>

Failing to specify :post results in the form thinking it should be PUTing instead of POSTing:

<form action="/threads/1/messages" class="thread_edit" id="thread_edit" method="post"><div style="margin:0;padding:0;display:inline"><input name="_method" type="hidden" value="put" />