Routing for sessions#destroy action

2019-06-28 01:50发布

问题:

I'm linking to the destroy action for the Sessions controller like this:

<%= link_to "Sign out", session_path, method: :delete  %>

Routes.rb:

resources :sessions, only: [:new, :create, :destroy]

Rails complains about the link above:

No route matches {:action=>"destroy", :controller=>"sessions"} missing required keys: [:id]

How do I link to the destroy action and keeping the REST/resource methodology in Rails when there's no object ID to provide for the link?

回答1:

It is best to treat the routes to your sessions controller as a singular resource

routes.rb

resource :sessions

Doc: http://guides.rubyonrails.org/routing.html#singular-resources

This will give you a route that you can use without ID's

DELETE /sessions sessions#destroy



回答2:

destroy is a member route, you need to pass id in the params to make it work, but you can do this to convert it to a collection route

resources :sessions, only: [:new, :create] do
  delete :destroy, on: :collection
end

Hope that helps!



回答3:

By default destroy method expects id, which should be pass with the link. For Ex. you are destroying session for logged in user, then you have to pass id or session of logged-in user, in this case, your link should be like this, <%= link_to "Sign out", session_path(user.id), method: :delete %> or if your purpose is to just delete/clear session only then you need to change in route.

resources :sessions, only: [:new, :create]
delete '/session', to: 'sessions#destroy'

If you want both types of link(In which we may pass ID or not), then you should try this route. delete '/session(/:id)', to: 'sessions#destroy'



回答4:

You need to pass the session resource to that route, like so:

<%= link_to "Sign out", session_path(session), method: :delete  %>

Rails show and delete actions require a resource.



回答5:

You need to change the path, which in your case can be /users/sign_out or sessions/sign_out and not /sessions with a DELETE method.

Take a look at devise's session destroy action and the route.

So, you could use something like

    resource :session do
      delete :destroy, path: 'sign_out', as: "destroy"
    end

Which will create path /session/sign_out which points to sessions#destroy and you can call it in your views as destroy_session_path.