How to manually specify a :delete request in the URL? - ruby-on-rails

Situation:
I want to destroy the current session in Rails, and am currently signed into an admin model setup via devise.
I thought it would be enough to input site.io/admins/sign_out into the URL, but this assumes a GET request and doesn't work.
No route matches [GET] "/admins/sign_out"
A method: :delete request needs to be made to destroy the session.
Can something be done like site.io/admins/sign_out{action:delete}?
UPDATE
Per request, this is the route related to admin.
devise_for :admins

try this:
<%= link_to "Sign Out", destroy_admin_session_path, :method => :delete %>

To log out with devise you need to POST to /admins/sign_out. I use rails link_to to help with this.
<%= link_to "Log Out", destroy_admin_session_path, method: :delete %>
You could also do it without ERB or link_to
<a rel="nofollow" data-method="delete" href="/admins/sign_out">Log Out</a>
For user model, just replace admin with user
<%= link_to "Log Out", destroy_user_session_path, method: :delete %>
or
<a rel="nofollow" data-method="delete" href="/users/sign_out">Log Out</a>
Source: https://github.com/plataformatec/devise/wiki/How-To:-Add-sign_in,-sign_out,-and-sign_up-links-to-your-layout-template

No you can not manually type in the link on the browser and log it out because in the browser you can't specify PUT POST or Delete.If you define the logout path as GET Method you can directly enter the path and log it out as browser by default gives a GET method. you can do it on Rest Client like postman like below
http://localhost:3000/users/sign_out.html
select method as DELETE

If you inject site.io/admins/sign_out forcefully.
It will send you to the show action of the controller with Parameters: {"id"=>"sign_out"}. Because It assumes that, it is a show action rather than calling the Delete function.
So, I think it is not possible, to forcefully use delete method directly from URL.

Related

Why do I get Rails 7 Routing Error although route is defined?

I'm following the Rails Tutorial by Michael Hartl to build a tiny demo app. I'm stuck at the logout. This is my routes.rb:
Rails.application.routes.draw do
resources :users
get "/login", to: "sessions#new"
post "/login", to: "sessions#create"
delete "/logout", to: "sessions#destroy"
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
root 'users#index'
end
This is the relevant controller action:
def destroy
log_out
redirect_to root_url, status: :see_other
end
This is the session helper defining log_out:
def log_out
reset_session
#current_user = nil
end
and this is the link tag in the view:
<%= link_to "Log out", logout_path, data: { 'turbo-method': :delete } %></span>
Screenshot of error
When I click on the logout link, I get this error. Expected behaviour: Log user out, redirect to login screen.
What am I doing wrong?
I don't know whether it's because of Turbo, or whether Turbo is even correctly installed. I've added gem 'turbo-rails' to the Gemfile and ran bundle afterwards without any effect.
For me, adding the method: :delete worked along with data-turbo.
<span>
<%= link_to "Log out", destroy_user_session_path,method: :delete, data: { 'turbo-method': :delete } %></span>
You were accessing the DELETE method route via GET. Have you run
rails turbo:install
You may want to change the sign out via GET instead of Delete in config/devise.rb
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :get # <= change this from :delete to :get and remove the `method:` in your `link_to` helper
Here's the references:
https://github.com/hotwired/turbo-rails
https://github.com/heartcombo/devise/issues/5439
Check with passing method
<%= link_to "Log out", logout_path, method: :delete, data: { 'turbo-method': :delete } %>
or
<%= link_to "Log out", logout_path, method: :delete %>
You can change link_to to button_to
<%= button_to "Log out", logout_path, method: :delete %>
It will be less magic but more reliable because not a link but form is used (in normal life, clicking on link is a GET request)

DELETE method not being used on sign out in Devise

I have Devise set up in my Rails application, but my sign out link:
<%= link_to "Sign out", destroy_user_session_path, method: :delete %>
is not working. The correct HTML seems to be generated:
<a rel="nofollow" data-method="delete" href="/users/sign_out">Sign out</a>
but there is no DELETE request being logged by Rails, only a 'GET /user/sign_out', which then throws an exception. What could be causing this?
Edit:
I've now discovered if I use button_to instead of link_to this works, so the issue certainly seems to be with the DELETE call not being generated client-side.

ActionController::InvalidAuthenticityToken error in rails

I wanted to add some custom fields to devise authentication, so I followed a tutorial and did some changes. I unpacked the devise gem, added the fields to the views, and devise controller. I added the fields "first_name" and "last_name" to my users table. The changes didn't work. So I didn't want to spend much time on that, so I wanted to move on, I removed all the code I added to the devise gem sourcecode, created a migration to remove first_name, and last_name from users. Everything looked fine, I can move about on the site and everything. But as soon as I try to sign out, I get this error:
In the command line, the error also says "can't verify CSRF token auhtenticity"
This is the code I have in my layout view navbar for the user to sign out:
<% if user_signed_in? %>
<li><%= link_to "Sign out", destroy_user_session_path, method: :delete %></li>
<%else%>
<li>
<%= link_to "sign up" , new_user_registration_path %>
</li>
<li>
<%= link_to "Log in", new_user_session_path%>
</li>
<%end%>
I restarted the server and all that. The user is still signed in. I can't do anything to sign out. Is there a way to fix this?
To destroy a user session in devise, you have to do the following:
<%= link_to "Logout", destroy_user_session_path, :method => :delete %>
the hash ':method' will trigger delete action and sign the user out and destroy current session. Make sure your pointing to your "destroy_user_session_path", or the path you specified. You should be able to see what the name of the path is by using "rails routes" or "rake routes" command depending on what version of rails you're using.
Hope this helps.

Devise destroy session doesn't destroy the session?

Really new to devise - it's very frustrating in all honesty...
My user session isn't being destroyed.
Here is the link in my navbar:
<li><%= link_to 'Logout', destroy_user_session_path, :method => :delete %></li>
devise.rb has the :delete method configured:
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
Route is:
destroy_user_session DELETE /users/sign_out(.:format) sessions#destroy
Application controller says :
class ApplicationController < ActionController::Base
protect_from_forgery
private
def after_sign_out_path_for(resource_or_scope)
root_path
end
I click my sign out link and my console shows :
Started GET "/users/sign_out" for 127.0.0.1 at 2014-04-18 12:00:26 -0500
Processing by UsersController#show as HTML
Parameters: {"id"=>"sign_out"}
MONGODB (0.8ms) waittext_development['users'].find({:_id=>BSON::ObjectId('53515685963e6507ad00003e')}).limit(-1)
It doesn't seem to be finding an active session (I've clicked it a dozen times in frustration), but the problem is the page I land out - UsersController#show - is not the page I've told it to route to. It should be the root_path which is users#index
So I was getting all these nil class errors on users#show because it was trying to render the default rails #user.name, etc. and #user isn't defined - I finally manually overrode the show action to simply render 'index' and I end up on my index page - BUT STILL - I'm seeing current_user.email printed here:
<% if user_signed_in? -%>
<ul>
<li><%= current_user.email %></li>
<li><%= link_to 'My info', edit_user_registration_path %></li>
<li><%= link_to 'Sign out', destroy_user_session_path %></li>
</ul>
It is evaluating TRUE and I'm getting those three list items.
User should not be signed in because I just destroyed the session!
What the heck?
You issue a GET request, not a DELETE (or even a POST with a set _method parameter to emulate a proper DELETE). As such, your request is routed to UsersController#show which listens to GET /users/:id.
The reason for that is, that a plain HTML link normally can only lead to GET requests. For anything else, you need a form. If you now pass the :method parameter to the link_to method in your view, Rails will generate some Javascript which captures the click on the link to generate a form and send the request that way. This will fail if the user has Javascript disabled, which seems to be the case here.
You should thus either ensure that all users (including you) have Javascript enabled or use something like button_to instead which will create a proper form in HTML which works without Javascript.
This is how i have implemented this so known to work:
devise_scope :user do
match "sign_out", :to => "sessions#destroy", via: [:delete]
end
<%= link_to sign_out_path, :method => "DELETE" do %>
<% end%>

Ruby link_to options

I need to add an id element into a session array in my rails application. I have the id when I bring up this view, product.id, and i have my session, called session[:cart], waiting for input.
I want to push that id into the session when I click on the link below.
<%= link_to "Add to Cart", controller: "my_cart" %>
Is there more to this link I add? i have been looking all over the internet and have not come up with exactly what I'm looking for.
Please help
You need to pass your product.id to some controller/action where that controller/action will add the product id to the session. It cant be done on the browser side as Sessions are server driven
<%= link_to "Add to Cart", add_product_to_cart_path(:product_id => product.id) %>
and method would be something like
def add_product_to_cart
session[:cart] << params[:product_id]
end
what you can do is make a action in controller where you can put product.id in your session[:cart] and put the path of that action into link_to for example:-
<%= link_to "Add to Cart",your_action_path %>
and to see the path of your action you can run rake routes in terminal, just put that path in there and it should do it

Resources