No route matches "/users/sign_out" devise rails 3 - ruby-on-rails

I've installed devise on my app and applied the following in my application.html.erb file:
<div id="user_nav">
<% if user_signed_in? %>
Signed in as <%= current_user.email %>. This cannot be cheese?
<%= link_to 'Sign out', destroy_user_session_path %>
<% else %>
<%= link_to 'Register', new_user_registration_path %> or <%= link_to 'Sign in', new_user_session_path %>
<% end %>
</div>
I ran rake routes and confirmed that all the routes are valid.
Also, in my routes.rb file I have devise_for :users and root :to => "home#index".
I get the following routing error when clicking the "Sign out" link:
No route matches "/users/sign_out"
Any ideas what's causing the error?

I think the route for signing out is a DELETE method. This means that your sign out link needs to look like this:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Yours doesn't include the :method => :delete part. Also, please note that for this to work you must also include <%= javascript_include_tag :defaults %> in your layout file (application.html.erb).

I changed this line in devise.rb:
config.sign_out_via = :delete
to
config.sign_out_via = :get
and it started working for me.

You probably didn't include jquery_ujs javascript file. Make sure you are using the latest version of jquery-ujs : https://github.com/rails/jquery-ujs and the last files available :
rails generate jquery:install
You should not have any more rails.js file. If you do, you're probably out-of-date.
Make sure also this file is loaded with defaults, in config/application.rb
config.action_view.javascript_expansions[:defaults] = %w(jquery.min jquery_ujs)
(Again, you should not have rails.js file here).
Finally, add the link as documented on Devise wiki (haml-style):
= link_to('Logout', destroy_user_session_path, :method => 'delete')
And everything will be fine.

The ability to make the Logout link a DELETE RESTful call requires an html attribute data-method = "delete" by using the rails code = link_to('Logout', destroy_user_session_path, :method => :delete).
However, if you do not have the gem jquery-ujs installed or are not calling the resulting javascript in your application.html via = javascript_include_tag "application", the response will be sent as a GET request, and the route will fail.
You have a few options if you do not want to use jquery-ujs or cannot find a way to make it work:
Change config.sign_out_via to equal :get within devise.rb (not recommended, since DELETE is the appropriate RESTful query)
OR Change the link_to to = button_to('Logout', destroy_user_session_path, :method => :delete). With button_to Rails will do the heavy lifting on making the proper DELETE call. You can then style the button to look like a link if you wish.

Try adding a new route to devise/sessions#destroy and linking to that. Eg:
routes.rb
devise_for :users do
get 'logout' => 'devise/sessions#destroy'
end
view:
<%= link_to "Logout", logout_path %>

Use it in your routes.rb file:
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end

I had the same problem with rails 3.1.0, and I solved adding in file the followings lines:
app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs

With one exception, Jessie's answer worked for me:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
change:
:delete
... to:
'delete'
So the code that worked for me is:
<%= link_to "Sign out", destroy_user_session_path, :method => 'delete' %>

Many answers to the question already. For me the problem was two fold:
when I expand my routes:
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
I was getting warning that this is depreciated so I have replaced it with:
devise_scope :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
I thought I will remove my jQuery. Bad choice. Devise is using jQuery to "fake" DELETE request and send it as GET. Therefore you need to:
//= require jquery
//= require jquery_ujs
and of course same link as many mentioned before:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>

Add:
<%= csrf_meta_tag %> and
<%= javascript_include_tag :defaults %> to layouts
Use these link_to tags
link_to 'Sign out', destroy_user_session_path, :method => :delete
or
link_to 'Sign out', '/users/sign_out', :method => :delete
In routes add:
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end

Other option is to configure the logout to be a GET instead a DELETE, you can do that adding the following line on /config/initializers/devise.rb
config.sign_out_via = :get
But as Steve Klabnik wrote on his blog (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html) try to use DELETE because of the semantic of this method.

If you are using Rails 3.1 make sure your application.html.erb sign out looks like:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
And that your javascript include line looks like the following
<%= javascript_include_tag 'application' %>
My guess is that some gems overwrite the new structure of the default.js location.

Check it out with source code in github:
https://github.com/plataformatec/devise/commit/adb127bb3e3b334cba903db2c21710e8c41c2b40#lib/generators/templates/devise.rb (date : June 27, 2011 )
# The default HTTP method used to sign out a resource. Default is :get.
188
# config.sign_out_via = :get
187
# The default HTTP method used to sign out a resource. Default is :delete.
188
config.sign_out_via = :delete

Well, guys for me it was only remove the :method => :delete
<%= link_to('Sign out', destroy_user_session_path) %>

This means you haven't generated the jquery files after you have installed the jquery-rails gem. So first you need to generate it.
rails generate devise:install
First Option:
This means either you have to change the following line on /config/initializers/devise.rb
config.sign_out_via = :delete to config.sign_out_via = :get
Second Option:
You only change this line <%= link_to "Sign out", destroy_user_session_path %> to <%= link_to "Sign out", destroy_user_session_path, :method => :delete %> on the view file.
Usually :method => :delete is not written by default.

I want to add to this even though it's a bit old.
the "sign_out" link didn't work, despite having :method => :delete.
The comment indicating that <%= javascript_include_tag :defaults %> must be included reminded me I had recently added JQuery java script and used simple <script src=""/> tags to include them.
When I moved them from after the :defaults to before, the sign_out started working again.
Hopefully this helps someone.

Most answers are partial. I have hit this issue many times. Two things need to be addressed:
<%= link_to(t('logout'), destroy_user_session_path, :method => :delete) %>
the delete method needs to be specified
Then devise uses jquery, so you need to load those
<%= javascript_include_tag "myDirectiveJSfile" %>
and ensure that BOTH jquery and jquery-ujs are specified in your myDirectiveJSfile.js
//= require jquery
//= require jquery_ujs

Don't forget to include the following line in your application.js (Rails 3)
//= require_self
//= require jquery
//= require jquery_ujs
Include jquery_ujs into my rails application and it works now.

devise_for :users
devise_scope :user do
get '/users/sign_out' => 'devise/sessions#destroy'
end

The problem begin with rails 3.1... in /app/assets/javascript/ just look for application.js.
If the file doesn't exist create a file with that name I don't know why my file disappear or never was created on "rails new app"....
That file is the instance for jquery....

Lots of solutions are there. but mostly use this,
<%= link_to 'Sign out', destroy_user_session_path, method: :delete %>
or config devise.rb with proper sign_out method
In devise.rb
config.sign_out_via = :delete ( or :get which u like to use.)

If you're using HTTPS with devise, it'll break if your sign-out link is to the non-secure version. On the back end, it redirects to the secure version. That redirect is a GET, which causes the issue.
Make sure your link uses HTTPS. You can force it with protocol: "https" in your url helper (make sure you use the url helper and not the path helper).
<%= link_to "Sign out", destroy_user_session_url(protocol: "https"), method: :delete %>

use :get and :delete method for your path:
devise_scope :user do
match '/users/sign_out' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:get, :delete]
end

In your routes.rb :
devise_for :users do
get '/sign_out' => 'devise/sessions#destroy'
get '/log_in' => 'devise/sessions#new'
get '/log_out' => 'devise/sessions#destroy'
get '/sign_up' => 'devise/registrations#new'
get '/edit_profile' => 'devise/registrations#edit'
end
and in your application.html.erb:
<%if user_signed_in?%>
<li><%= link_to "Sign_out", sign_out_path %></li>
<% end %>

This is what I did (with Rails 3.0 and Devise 1.4.2):
Make sure your page loads rails.js
Use this param: 'data-method' => 'delete'
Good idea to add this param: :rel => 'nofollow'

I am using rails 7. So This was how I had to do it. The important bit is data: { turbo_method: :delete }
<%= link_to t('nav.logout'), destroy_user_session_path, class: "nav-link", data: { turbo_method: :delete } %>
Below were the defaults created by rails when I generated the project.
application.html.erb
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
application.js
import "#hotwired/turbo-rails"
import "./controllers"
import * as bootstrap from "bootstrap"

See if your routes.rb has a "resource :users" before a "devise_for :users" then try swapping them:
Works
devise_for :users
resources :users
Fails
resources :users
devise_for :users

the ':method => :delete' in page is 'data-method="delete"'
so your page must have jquery_ujs.js, it will submit link with method delete not method get

I know this is an old question based on Rails 3 but I just ran into and solved it on Rails 4.0.4. So thought I'd pitch in how I fixed it for anyone encountering this problem with this version. Your mileage may vary but here's what worked for me.
First make sure you have the gems installed and run bundle install.
gem 'jquery-rails'
gem 'turbolinks'
gem 'jquery-turbolinks'
In application.js check that everything is required like below.
Beware if this gotcha: it's //= require jquery.turbolinks and not //= require jquery-turbolinks
//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require turbolinks
//= require_tree .
Next, add the appropriate links in the header of application.html.erb.
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= javascript_include_tag :defaults %>
There seems to be many variations on how to implement the delete method which I assume depends on the version of Rails you are using.
This is the delete syntax I used.
<p><%= link_to "Sign Out", destroy_user_session_path, :method => 'delete' %></p>
Hope that helps dig someone out of this very frustrating hole!

In general when you get "No route matches" but you think you have that route defined then double check the http verb / request method (whether its get, put, post, delete etc.) for that route.
If you run rake routes then you will see the expected method and you can compare this with the request log.

Related

Devise: 'Couldn't find User with 'id'=sign_out' [duplicate]

I've installed devise on my app and applied the following in my application.html.erb file:
<div id="user_nav">
<% if user_signed_in? %>
Signed in as <%= current_user.email %>. This cannot be cheese?
<%= link_to 'Sign out', destroy_user_session_path %>
<% else %>
<%= link_to 'Register', new_user_registration_path %> or <%= link_to 'Sign in', new_user_session_path %>
<% end %>
</div>
I ran rake routes and confirmed that all the routes are valid.
Also, in my routes.rb file I have devise_for :users and root :to => "home#index".
I get the following routing error when clicking the "Sign out" link:
No route matches "/users/sign_out"
Any ideas what's causing the error?
I think the route for signing out is a DELETE method. This means that your sign out link needs to look like this:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Yours doesn't include the :method => :delete part. Also, please note that for this to work you must also include <%= javascript_include_tag :defaults %> in your layout file (application.html.erb).
I changed this line in devise.rb:
config.sign_out_via = :delete
to
config.sign_out_via = :get
and it started working for me.
You probably didn't include jquery_ujs javascript file. Make sure you are using the latest version of jquery-ujs : https://github.com/rails/jquery-ujs and the last files available :
rails generate jquery:install
You should not have any more rails.js file. If you do, you're probably out-of-date.
Make sure also this file is loaded with defaults, in config/application.rb
config.action_view.javascript_expansions[:defaults] = %w(jquery.min jquery_ujs)
(Again, you should not have rails.js file here).
Finally, add the link as documented on Devise wiki (haml-style):
= link_to('Logout', destroy_user_session_path, :method => 'delete')
And everything will be fine.
The ability to make the Logout link a DELETE RESTful call requires an html attribute data-method = "delete" by using the rails code = link_to('Logout', destroy_user_session_path, :method => :delete).
However, if you do not have the gem jquery-ujs installed or are not calling the resulting javascript in your application.html via = javascript_include_tag "application", the response will be sent as a GET request, and the route will fail.
You have a few options if you do not want to use jquery-ujs or cannot find a way to make it work:
Change config.sign_out_via to equal :get within devise.rb (not recommended, since DELETE is the appropriate RESTful query)
OR Change the link_to to = button_to('Logout', destroy_user_session_path, :method => :delete). With button_to Rails will do the heavy lifting on making the proper DELETE call. You can then style the button to look like a link if you wish.
Try adding a new route to devise/sessions#destroy and linking to that. Eg:
routes.rb
devise_for :users do
get 'logout' => 'devise/sessions#destroy'
end
view:
<%= link_to "Logout", logout_path %>
Use it in your routes.rb file:
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
I had the same problem with rails 3.1.0, and I solved adding in file the followings lines:
app/assets/javascripts/application.js
//= require_tree
//= require jquery
//= require jquery_ujs
With one exception, Jessie's answer worked for me:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
change:
:delete
... to:
'delete'
So the code that worked for me is:
<%= link_to "Sign out", destroy_user_session_path, :method => 'delete' %>
Many answers to the question already. For me the problem was two fold:
when I expand my routes:
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
I was getting warning that this is depreciated so I have replaced it with:
devise_scope :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
I thought I will remove my jQuery. Bad choice. Devise is using jQuery to "fake" DELETE request and send it as GET. Therefore you need to:
//= require jquery
//= require jquery_ujs
and of course same link as many mentioned before:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Add:
<%= csrf_meta_tag %> and
<%= javascript_include_tag :defaults %> to layouts
Use these link_to tags
link_to 'Sign out', destroy_user_session_path, :method => :delete
or
link_to 'Sign out', '/users/sign_out', :method => :delete
In routes add:
devise_for :users do
get '/users/sign_out' => 'devise/sessions#destroy'
end
Other option is to configure the logout to be a GET instead a DELETE, you can do that adding the following line on /config/initializers/devise.rb
config.sign_out_via = :get
But as Steve Klabnik wrote on his blog (http://blog.steveklabnik.com/2011/12/11/devise-actioncontroller-routingerror-no-route-matches-get-slash-users-slash-sign-out.html) try to use DELETE because of the semantic of this method.
If you are using Rails 3.1 make sure your application.html.erb sign out looks like:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
And that your javascript include line looks like the following
<%= javascript_include_tag 'application' %>
My guess is that some gems overwrite the new structure of the default.js location.
Check it out with source code in github:
https://github.com/plataformatec/devise/commit/adb127bb3e3b334cba903db2c21710e8c41c2b40#lib/generators/templates/devise.rb (date : June 27, 2011 )
# The default HTTP method used to sign out a resource. Default is :get.
188
# config.sign_out_via = :get
187
# The default HTTP method used to sign out a resource. Default is :delete.
188
config.sign_out_via = :delete
Well, guys for me it was only remove the :method => :delete
<%= link_to('Sign out', destroy_user_session_path) %>
This means you haven't generated the jquery files after you have installed the jquery-rails gem. So first you need to generate it.
rails generate devise:install
First Option:
This means either you have to change the following line on /config/initializers/devise.rb
config.sign_out_via = :delete to config.sign_out_via = :get
Second Option:
You only change this line <%= link_to "Sign out", destroy_user_session_path %> to <%= link_to "Sign out", destroy_user_session_path, :method => :delete %> on the view file.
Usually :method => :delete is not written by default.
I want to add to this even though it's a bit old.
the "sign_out" link didn't work, despite having :method => :delete.
The comment indicating that <%= javascript_include_tag :defaults %> must be included reminded me I had recently added JQuery java script and used simple <script src=""/> tags to include them.
When I moved them from after the :defaults to before, the sign_out started working again.
Hopefully this helps someone.
Most answers are partial. I have hit this issue many times. Two things need to be addressed:
<%= link_to(t('logout'), destroy_user_session_path, :method => :delete) %>
the delete method needs to be specified
Then devise uses jquery, so you need to load those
<%= javascript_include_tag "myDirectiveJSfile" %>
and ensure that BOTH jquery and jquery-ujs are specified in your myDirectiveJSfile.js
//= require jquery
//= require jquery_ujs
Don't forget to include the following line in your application.js (Rails 3)
//= require_self
//= require jquery
//= require jquery_ujs
Include jquery_ujs into my rails application and it works now.
devise_for :users
devise_scope :user do
get '/users/sign_out' => 'devise/sessions#destroy'
end
The problem begin with rails 3.1... in /app/assets/javascript/ just look for application.js.
If the file doesn't exist create a file with that name I don't know why my file disappear or never was created on "rails new app"....
That file is the instance for jquery....
Lots of solutions are there. but mostly use this,
<%= link_to 'Sign out', destroy_user_session_path, method: :delete %>
or config devise.rb with proper sign_out method
In devise.rb
config.sign_out_via = :delete ( or :get which u like to use.)
If you're using HTTPS with devise, it'll break if your sign-out link is to the non-secure version. On the back end, it redirects to the secure version. That redirect is a GET, which causes the issue.
Make sure your link uses HTTPS. You can force it with protocol: "https" in your url helper (make sure you use the url helper and not the path helper).
<%= link_to "Sign out", destroy_user_session_url(protocol: "https"), method: :delete %>
use :get and :delete method for your path:
devise_scope :user do
match '/users/sign_out' => 'devise/sessions#destroy', :as => :destroy_user_session, via: [:get, :delete]
end
In your routes.rb :
devise_for :users do
get '/sign_out' => 'devise/sessions#destroy'
get '/log_in' => 'devise/sessions#new'
get '/log_out' => 'devise/sessions#destroy'
get '/sign_up' => 'devise/registrations#new'
get '/edit_profile' => 'devise/registrations#edit'
end
and in your application.html.erb:
<%if user_signed_in?%>
<li><%= link_to "Sign_out", sign_out_path %></li>
<% end %>
This is what I did (with Rails 3.0 and Devise 1.4.2):
Make sure your page loads rails.js
Use this param: 'data-method' => 'delete'
Good idea to add this param: :rel => 'nofollow'
I am using rails 7. So This was how I had to do it. The important bit is data: { turbo_method: :delete }
<%= link_to t('nav.logout'), destroy_user_session_path, class: "nav-link", data: { turbo_method: :delete } %>
Below were the defaults created by rails when I generated the project.
application.html.erb
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
application.js
import "#hotwired/turbo-rails"
import "./controllers"
import * as bootstrap from "bootstrap"
See if your routes.rb has a "resource :users" before a "devise_for :users" then try swapping them:
Works
devise_for :users
resources :users
Fails
resources :users
devise_for :users
the ':method => :delete' in page is 'data-method="delete"'
so your page must have jquery_ujs.js, it will submit link with method delete not method get
I know this is an old question based on Rails 3 but I just ran into and solved it on Rails 4.0.4. So thought I'd pitch in how I fixed it for anyone encountering this problem with this version. Your mileage may vary but here's what worked for me.
First make sure you have the gems installed and run bundle install.
gem 'jquery-rails'
gem 'turbolinks'
gem 'jquery-turbolinks'
In application.js check that everything is required like below.
Beware if this gotcha: it's //= require jquery.turbolinks and not //= require jquery-turbolinks
//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require turbolinks
//= require_tree .
Next, add the appropriate links in the header of application.html.erb.
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= javascript_include_tag :defaults %>
There seems to be many variations on how to implement the delete method which I assume depends on the version of Rails you are using.
This is the delete syntax I used.
<p><%= link_to "Sign Out", destroy_user_session_path, :method => 'delete' %></p>
Hope that helps dig someone out of this very frustrating hole!
In general when you get "No route matches" but you think you have that route defined then double check the http verb / request method (whether its get, put, post, delete etc.) for that route.
If you run rake routes then you will see the expected method and you can compare this with the request log.

Devise logout fails if there is no `javascript_include_tag :all`

Session destroy by using Devise fails.
But if I rewrite <%= javascript_include_tag :application %> to <%= javascript_include_tag :all %>.
But latter way is now deprecated as far as I know.
I disabled turbolinks, and my config are like these.
config/routes.rb
devise_for :users, path_names: {sign_in: "login", sign_out: "logout"}, controllers: { omniauth_callbacks: "omniauth_callbacks" }
app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require foundation
//= require_tree .
$(function(){ $(document).foundation(); });
and logout link.
<%= link_to "log out", destroy_user_session_path, method: :delete %>
and error message is ActionController::RoutingError (No route matches [DELETE] "/users/logout"):
I thought <%= javascript_include_tag :application %> is same with <%= javascript_include_tag :all %> if I write application.js correctly.
I have no idea why this happens, and how to solve this problem?
I don't want to use deprecated :all method.
It looks like Rails didn't find the route. You can check in devise.rb if the configuration is
config.sign_out_via = :delete
I think default is ":delete" if the devise version is not very old. But it could be ":get", if it is ":get", either you change the config to
config.sign_out_via = :delete
or change the log out link to
<%= link_to "log out", destroy_user_session_path, method: :get %>
Or no matter what, all use ":get" to take a shot.

Devise/Rails: No route matches [GET] "/users/sign_out"

I'm a bit confused about how devise is routing my requests, for some reason I can't go to the sign-out path in my app now:
ActionController::RoutingError (No route matches [GET] "/users/sign_out")
Here is what my routes related to my User model and Devise look like:
devise_for :users, :controllers => {:registrations => "registrations"}
devise_scope :user do
get '/settings' => 'registrations#edit'
end
Would defining that scope prevent my other routes from working as well?
Update
I don't think that it's supposed to be GET request, as my link looks like:
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
If you try to go to /users/sign_out by typing it in the address bar of your browser, or linking to it normally, you will get this error. To summarize some comments and answers here and from issues at the devise repo on github:
This is the intended functionality, RESTful apps should not modify state with a GET request.
You can fix this by making a link that uses the DELETE method as mentioned by #Trip, #fuzzyalej, and the update by #Joseph Silvashy.
Alternatively, (and less recommended), in /config/initializers/devise.rb, you could make the following change
config.sign_out_via = :delete
to
config.sign_out_via = :get
I came across this issue while following along with http://railscasts.com/episodes/209-introducing-devise and with the older version of devise he's using there, this was not an issue.
Keep your devise.rb using the correct HTTP method:
# good
config.sign_out_via = :delete
# bad
config.sign_out_via = :get
Use button_to instead of link_to
# good
= button_to "Sign Out", destroy_user_session_path, method: :delete
# bad
= link_to "Sign Out", destroy_user_session_path, method: :delete"
If you are using bootstrap (keep it classy)
= link_to "Sign Out", destroy_user_session_path, method: :delete, class: "btn btn-default btn-sm"
Just so this post has an answer :
This must be sent with the method, delete so that it does not default to a get
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
devise_for :users
devise_scope :user do
get '/users/sign_out' => 'devise/sessions#destroy'
end
in your routes.rb.
If you're using SSL with Devise controllers, and trying to sign out from an 'http' url, what's happening is it's sending the DELETE request to the #destroy method, but then redirecting to the https version via GET. You can fix this by adding the https to the sign out link like so:
= link_to "Sign out", destroy_user_session_url(protocol: 'https'), method: :delete
Note: must be 'url' instead of 'path'
in Rails 7 the destroy_user_session_path changes a bit on the method.
instead of using the traditional method: :delete that came with the jquery and rails_ujs. Now you need to change that to ..., data: {turbo_method: :delete} and you don't need to setup any additional rails_ujs or jquery
From the rails documentation:
link_to("Destroy", "http://www.example.com", :method => :delete, :confirm => "Are you sure?")
# => Destroy
I had the same problem and to solve it took these steps:
1) include the //= require jquery_ujs in the assets/javascripts/application.js
2) add gem 'jquery-rails' to my gemfile
3) bundle install
... and it worked.

Why Rails "link_to" does not work for delete action?

In index.html.erb I display all products, and next to each product I have Edit and Delete actions:
<% #products.each do |product| %>
...
<%= link_to("Edit", edit_product_path(product.id), :class => 'action') %>
<%= link_to("Delete", product, :method => :delete, :class => 'action') %>
...
<% end %>
The Edit link works ok. However, the Delete link does not work. I get the following error:
Unknown action
The action 'show' could not be found for ProductsController
I guess it is because the request method is GET rather than DELETE. But, I don't know why this happens if I set explicitly :method => :delete.
routes.rb is pretty simple:
root :to => "products#index"
resources :products
I have Javascript enabled.
Please suggest.
Do you have rails.js specified in a javascript_include_tag? This is required for the unobtrusive DELETE method to work. If you're using jQuery then there's a solution for that too.
Dont forget to include jquery_ujs in your application.js file:
//
//= require jquery
//= require jquery_ujs
// ...
It needs to be product_path(product) instead of product in your delete link.
I had same problem - actually I had changed my old 'delete' action to 'destroy' - but forgot If your using SSL.. (e.g ssl_required :destroy)

link_to delete url is not working

I have the following link_to delete url in my app
<%=link_to "Delete",blog_path(#blog.id), :method => :delete, :class => "delete", :confirm => "Are you sure ?"%>
It does not seem to be working.When I click this url, it just takes me to the show path.Can someone please tell me how to fix this. Thanks.
Are you using jQuery? If so, I think the problem could be that you are using jQuery without the updated rails.js file.
Download rails.js here:
https://github.com/rails/jquery-ujs/raw/master/src/rails.js
Drop it in your javascripts directory, overwriting the rails.js that comes default with rails.
Add a javascript include line to include it.
<%= javascript_include_tag "rails" %>
Put this after your Jquery include tag. You probably also want to disinclude the javascript defaults if you don't plan on using prototype.
I included jQuery UI in my application, I found that delete is now working as show, but after doing above Resolved Issue.
Make sure these lines appear in application.js :
//= require jquery
//= require jquery_ujs
Ensure that you have java script turned on. Otherwise :method => :delete acts just as show in Rails.
If you're using restful routing for blogs, then the following should work:
<%= link_to "Delete", #blog, :method => :delete, :confirm => "Are you sure ?"%>
You can try with 'data-method' instead of :method.
<%=link_to "Delete",blog_path(#blog.id), 'data-method' => :delete, :class => "delete", :confirm => "Are you sure ?"%>
You can check on jquery_ujs.js the following piece of code:
// Handles "data-method" on links such as:
// Delete
In order for link_to to work with the delete method, Rails needs the unobtrusive scripting adapter for jQuery.
Make sure that your Gemfile has
gem 'jquery-rails'
Make sure that app/assets/javascripts/application.js has
//= require jquery
//= require jquery_ujs
Make sure that your app/views/layouts/application.html.erb has
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
inside the head tag. Remove the 'data-turbolinks-track' => true section if you don't plan to use Turbolinks.
you should use
<%=button_to "Delete",blog_path(#blog.id), :method => :delete, :class => "delete", :confirm => "Are you sure ?"%>
It's possible to have a working link_to without jQuery
I've found the best process to make a working delete link for ruby on rails without jQuery! Here I already make an answer: https://stackoverflow.com/a/67710994/14387700
But for making this easy, I'm writing this here again.
We need to work with 3 things:
Adding destroy method in articles_controller.rb
routes.rb setup
LINK_TO tag
Let's Start...
Adding destroy method in articles_controller.rb
At first, we will add def destroy ... end in articles_controller.rb,
lets open:
# app/controllers/articles_controller.rb
def destroy
#article = Article.find(params[:id])
#article.destroy
params[:id] = nil
flash[:notice] = "Art has been deleted"
redirect_to :action => :index
end
Here
in the 1st line, we're calling a variable '#article' which will find and select the ID parameters of the article on rails console from our database. Then,
in 2nd line, the #article variable will make the destroy command in the console. then,
in 3rd line: the id params will be deleted and
in 4th line, a notice will flash in application page "Art has been deleted" and also will show in console that, found nothing in the database.
In 5th line, after the destroying process completed, we will be redirected to the article index page.
This is the main factor which will give the destroying command. and make the link_to working.
Setup routes.rb
BUT WAIT
We need 2 routes for the destroy page which are:
A GET protocol setup
A DELETE protocol setup
In routes just add:
resources :articles, except: [:destroy] # this will add all get request links automatically except destroy link
post '/articles/new' => 'articles#create'
post '/articles/:id' => 'articles#update'
post '/articles/:id/edit' => 'articles#update' # this 3 lines are needed for other forms purpose
# we need this 2 lines for our delete link_to setup
delete 'articles/:id/delete' => 'articles#destroy', as: 'articles_delete'
get '/articles/:id/delete' => 'articles#destroy'
Here
The 2nd last line is declaring the DELETE method,
'articles/:id/delete' will be the link structure in post link tag (known as: anchor tag in HTML) for every single post,
'=>' is pointing the link structure to the controller tag which is 'articles#destroy',
then we defined the path text by setting ** as: 'articles_delete'** which we will use as:
'articles_delete_path' or 'articles_delete_url' in link_to tag.
Then
in last line, we defined the get request for the delete link which will give us a working link like "https://2haas.com/articles/1/delete" except "/articles/1/destroy" that means we can customize our delete link from this 2 methods setup with more additional information..
Last sweetest delete output
The desired link_to tag
we can use this to get proper delete link_to tag which will work.
<%= link_to 'Delete Article', articles_delete_path, method: :delete %>
<%= link_to 'Delete Article', articles_delete_url, method: :delete %>
<% obj.each do |post| %>
<%= link_to 'Delete Article', articles_delete_path(post), method: :delete %>
<% end %>
AND that's done except jQuery
Thanks for reading this answer properly.!
HAPPY PROGRAMMINGS

Resources