简体   繁体   中英

using form_for with a singular model

I have a Wizard model that the client references w/o an ID (it's saved in the session), so I've created a singular resource for :show and :update. I want the admin to have access to all instances of that model via index so admin can delete strays, so I've added a plural resources for :index and :destroy. The index and destroy works, but I can't figure out the right arguments to pass to form_for in the update view.

The setup

# config/routes.rb
WTest::Application.routes.draw.do
  resource :wizard, :only => [:show, :update]
  resources :wizards, :only => [:index, :destroy]
  ...
end

resulting in

$ rake routes
wizards GET    /wizards(.:format)     {:action=>"index", :controller=>"wizards"}
 wizard DELETE /wizards/:id(.:format) {:action=>"destroy", :controller=>"wizards"}
        GET    /wizard(.:format)      {:action=>"show", :controller=>"wizards"}
        PUT    /wizard(.:format)      {:action=>"update", :controller=>"wizards"}

This sets up routes the way I'd expect.

The question (revised since original post)

In the console:

>> app.wizard_path

raises the error ActionController::RoutingError: No route matches {:action=>"destroy", :controller=>"wizards"}

Why is this? Have I set up my routes incorrectly? I need to specify :url => wizard_path for form_for() in the wizards's update view.

The details

If I specify an explicit path in my call to form_for:

# app/view/wizards/update.html.erb
<%= form_for @wizard, :url => wizard_path do |f| %>
  <%= f.submit %>
<% end %>

... then attempting to render this for gets an error on the form_for line:

No route matches {:action=>"destroy", :controller=>"wizards"}

I have no idea why it's trying to match the destroy action. How do I get the form to submit to the {action=>"update", :controller=>"wizards"} route?

(By the way, I looked at bug 267 , and I don't think it is the same as what I'm observing. But if it is this bug, is there a workaround?)

Carrying on the long tradition of answering my own questions (meh!), I think I figured it out. If my analysis is wrong, I'd be happy to give someone else the checkmark...

The cause of the problem

Look at the output of rake routes

$ rake routes
wizards GET    /wizards(.:format)     {:action=>"index", :controller=>"wizards"}
 wizard DELETE /wizards/:id(.:format) {:action=>"destroy", :controller=>"wizards"}
        GET    /wizard(.:format)      {:action=>"show", :controller=>"wizards"}
        PUT    /wizard(.:format)      {:action=>"update", :controller=>"wizards"}

The path method 'wizard_path' is ambiguous: it can either refer to the DELETE clause, in which case it needs an :id argument ( wizard_path(22) ), or it can refer to the GET and PUT clauses, in which case it doesn't take an ID argument.

The solution

So my solution was to create a route specifically for deletion. My revised routes.rb file now reads:

resources :wizards, :only => [:index]
resource :wizard, :only => [:show, :update]
match 'wizard/:id' => 'wizards#destroy', :via => :delete, :as => :delete_wizard

and rake routes now produces:

$ rake routes
      wizards GET    /wizards(.:format)    {:action=>"index", :controller=>"wizards"}
       wizard GET    /wizard(.:format)     {:action=>"show", :controller=>"wizards"}
              PUT    /wizard(.:format)     {:action=>"update", :controller=>"wizards"}
delete_wizard DELETE /wizard/:id(.:format) {:controller=>"wizards", :action=>"destroy"}

I needed to make a one-line change to the delete link in wizards/index.html.erb to use the new delete_wizard_path, but everything works now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM