Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The url_for method cannot find the route

I have to make edit/create forms for several tables on one page (settings). Therefore I have created SettingsController.

Routes:

resources :settings, :only => :index do
  member do
    get 'cs_edit'
    put 'cs_update'
    post 'cs_create'
    delete 'cs_destroy'
  end
end

The controller:

class SettingsController < ApplicationController
  before_filter :authenticate
...
def cs_create
  @cs = CaseStatus.find(params[:id])
  @cs.save

  redirect_to settings_path, :notice => 'Case Status was created successfully'
end

The view part:

<%= form_for(@cs, :url => url_for(:action => 'cs_create', :controller => 'settings'), :class => 'status_form') do |cs_f| %>

The question is that I am getting the following error:

Showing /home/michael/public_html/development/fbtracker/app/views/settings/index.html.erb where line #98 raised:

No route matches {:action=>"cs_create", :controller=>"settings"}
Extracted source (around line #98):

95:                   <% end %>
96:                 </table>
97: 
98:                 <%= form_for(@cs, :url => url_for(:action => 'cs_create', :controller => 'settings'), :class => 'status_form') do |cs_f| %>
99:                   <%= cs_f.text_field :name, :class => 'sname' %>
100:                  <%= cs_f.text_field :owt, :class => 'owt' %>
101:                  <%= cs_f.submit 'Add' %>

Also I just have checked routes:

$ rake routes
...
cs_edit_setting GET    /settings/:id/cs_edit(.:format)             {:action=>"cs_edit", :controller=>"settings"}
cs_update_setting PUT    /settings/:id/cs_update(.:format)           {:action=>"cs_update", :controller=>"settings"}
cs_create_setting POST   /settings/:id/cs_create(.:format)           {:action=>"cs_create", :controller=>"settings"}
cs_destroy_setting DELETE /settings/:id/cs_destroy(.:format)          {:action=>"cs_destroy", :controller=>"settings"}
settings GET    /settings(.:format)                         {:action=>"index", :controller=>"settings"}

As you can see, the route matches {:action=>"cs_create", :controller=>"settings"} is exist. But url_for cannot find this route. Why?

like image 741
Don Tomato Avatar asked Oct 10 '22 20:10

Don Tomato


1 Answers

You have defined cs_create as a member method, but your url_for call doesn't give it an object. If you really want to use url_for this way, you can do this:

url_for(:id => @cs.id, :action => 'cs_create', :controller => 'settings')

Or alternatively make it a collection method:

resources :settings, :only => :index do
  post 'cs_create', :on => :collection
  member do
    get 'cs_edit'
    put 'cs_update'
    delete 'cs_destroy'
  end
end

However, as mentioned in the comments, this is basically ignoring all of the support that rails provides to make this easy. I'd recommend:

  • define a resources routing for CaseStatus that can use all the standard RESTful routes (that doesn't mean you can't make all these settings visible on a single page under /settings
  • use standard url helpers instead of url_for
  • understand that you don't need a separate path for all the HTTP actions (e.g. show, update and delete are usually share all the same path, but with different HTTP actions)
like image 131
tardate Avatar answered Oct 13 '22 09:10

tardate