title: Rails 3 Form For Custom Action
body: <p>I'm having trouble routing a form to a custom action in Rails 3. Here are my routes:</p>
  
  <pre><code>resources :photos do
      resources :comments
      collection do
          get 'update_states'
      end
      member do
          put 'upload'
      end
  end
  </code></pre>
  
  <p>Here's the form_for:</p>
  
  <pre><code>form_for @photo, :remote =&gt; true, :url =&gt; { :action =&gt; upload_photo_path(@photo) }, :html =&gt; { :multipart =&gt; :true, :method =&gt; 'put' } do |f|
  </code></pre>
  
  <p>And here's the error message:</p>
  
  <pre><code>No route matches {:action=&gt;"/photos/42/upload", :controller=&gt;"photos"}
  </code></pre>
  
  <p>... this is especially frustrating because "photos/:id/upload" is <em>exactly</em> the correct action for this form.</p>
  
  <p>What am I missing?</p>
  
  <p>EDITS - Here are the original Photo-related routes:</p>
  
  <pre><code>   photo_comments    GET    /photos/:photo_id/comments(.:format)          {:action=&gt;"index", :controller=&gt;"comments"}
                       POST   /photos/:photo_id/comments(.:format)          {:action=&gt;"create", :controller=&gt;"comments"}
     new_photo_comment GET    /photos/:photo_id/comments/new(.:format)      {:action=&gt;"new", :controller=&gt;"comments"}
    edit_photo_comment GET    /photos/:photo_id/comments/:id/edit(.:format) {:action=&gt;"edit", :controller=&gt;"comments"}
         photo_comment GET    /photos/:photo_id/comments/:id(.:format)      {:action=&gt;"show", :controller=&gt;"comments"}
                       PUT    /photos/:photo_id/comments/:id(.:format)      {:action=&gt;"update", :controller=&gt;"comments"}
                       DELETE /photos/:photo_id/comments/:id(.:format)      {:action=&gt;"destroy", :controller=&gt;"comments"}
  update_states_photos GET    /photos/update_states(.:format)               {:action=&gt;"update_states", :controller=&gt;"photos"}
          upload_photo PUT    /photos/:id/upload(.:format)                  {:action=&gt;"upload", :controller=&gt;"photos"}
                photos GET    /photos(.:format)                             {:action=&gt;"index", :controller=&gt;"photos"}
                       POST   /photos(.:format)                             {:action=&gt;"create", :controller=&gt;"photos"}
             new_photo GET    /photos/new(.:format)                         {:action=&gt;"new", :controller=&gt;"photos"}
            edit_photo GET    /photos/:id/edit(.:format)                    {:action=&gt;"edit", :controller=&gt;"photos"}
                 photo GET    /photos/:id(.:format)                         {:action=&gt;"show", :controller=&gt;"photos"}
                       PUT    /photos/:id(.:format)                         {:action=&gt;"update", :controller=&gt;"photos"}
                       DELETE /photos/:id(.:format)                         {:action=&gt;"destroy", :controller=&gt;"photos"}
  </code></pre>
  
  <p>Here are the relevant routes when I changed the route to <code>match 'upload'</code>:</p>
  
  <pre><code> photo_comments GET    /photos/:photo_id/comments(.:format)          {:action=&gt;"index", :controller=&gt;"comments"}
                       POST   /photos/:photo_id/comments(.:format)          {:action=&gt;"create", :controller=&gt;"comments"}
  }
     new_photo_comment GET    /photos/:photo_id/comments/new(.:format)      {:action=&gt;"new", :controller=&gt;"comments"}
    edit_photo_comment GET    /photos/:photo_id/comments/:id/edit(.:format) {:action=&gt;"edit", :controller=&gt;"comments"}
         photo_comment GET    /photos/:photo_id/comments/:id(.:format)      {:action=&gt;"show", :controller=&gt;"comments"}
                       PUT    /photos/:photo_id/comments/:id(.:format)      {:action=&gt;"update", :controller=&gt;"comments"}
                       DELETE /photos/:photo_id/comments/:id(.:format)      {:action=&gt;"destroy", :controller=&gt;"comments"}
  update_states_photos GET    /photos/update_states(.:format)               {:action=&gt;"update_states", :controller=&gt;"photos"}
          upload_photo        /photos/:id/upload(.:format)                  {:action=&gt;"upload", :controller=&gt;"photos"}
                photos GET    /photos(.:format)                             {:action=&gt;"index", :controller=&gt;"photos"}
                       POST   /photos(.:format)                             {:action=&gt;"create", :controller=&gt;"photos"}
             new_photo GET    /photos/new(.:format)                         {:action=&gt;"new", :controller=&gt;"photos"}
            edit_photo GET    /photos/:id/edit(.:format)                    {:action=&gt;"edit", :controller=&gt;"photos"}
                 photo GET    /photos/:id(.:format)                         {:action=&gt;"show", :controller=&gt;"photos"}
                       PUT    /photos/:id(.:format)                         {:action=&gt;"update", :controller=&gt;"photos"}
                       DELETE /photos/:id(.:format)                         {:action=&gt;"destroy", :controller=&gt;"photos"}
  </code></pre>
  
  <p>Unfortunately 'match' didn't work any better...</p>
  
  <p>-- EDIT --</p>
  
  <p>Just to confirm another scenario here... with this in the routes:</p>
  
  <pre><code>resources :photos do
      resources :comments
      collection do
          get 'update_states'
      end
      member do
          match 'upload'
      end
  end
  </code></pre>
  
  <p>and this in the view:</p>
  
  <p><code>form_for @photo, :remote =&gt; true, :url =&gt; { :action =&gt; 'upload' }, :html =&gt; { :multipart =&gt; :true, :id =&gt; 'photo_upload' } do |f|</code></p>
  
  <p>I still get:</p>
  
  <p><code>No route matches {:action=&gt;"upload", :controller=&gt;"photos"}</code></p>