How to devise destroy session and sign out from controller? - ruby-on-rails

Devise destroy session and sign out from controller?
if something_is_not_kosher
# 1. log this event, 2. send notice
redirect_to destroy_user_session_path and return
end
Also tried:
if something_is_not_kosher
# 1. log this event, 2. send notice
redirect_to controller: 'devise/sessions', action: 'destroy', method: :delete and return
end
Error is No route matches [GET] "/users/sign_out" but I'm explicitly setting method: :delete in example 2. Maybe devise has a method? current_user.sign_out and tried sign_out(current_user) which also don't work? Thanks for the help.
rake routes:
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) users/registrations#cancel
user_registration POST /users(.:format) users/registrations#create
new_user_registration GET /users/sign_up(.:format) users/registrations#new
edit_user_registration GET /users/edit(.:format) users/registrations#edit
PATCH /users(.:format) users/registrations#update
PUT /users(.:format) users/registrations#update
DELETE /users(.:format) users/registrations#destroy

Why don't you just use devise's built-in sign_out_and_redirect(current_user) method?

So I ended up solving this by creating a custom signout route
devise_scope :user do
get '/signout', to: 'devise/sessions#destroy', as: :signout
end
and in my controller I have:
if something_is_not_kosher
redirect_to signout_path and return
end

destroy_user_session_path(#user) is sign out path for user, but it must requst with DELETE method. redirect_to method will tell broswer to request another path, but broswer just can request with GET method.
So if you want to let user to sign out, you must set a sign out form with DELETE method or with AJAX request to let user sign out but not with redirect_to function.
If you just want to destroy user session, use sign_out #user is ok.

Just in case someone can't use it directly.
<% if user_signed_in? %>
<li><%= link_to "Logout", destroy_user_session_path, :method => :delete %></li>
<% else %>
<li><%= link_to "Sign up now!", new_user_registration_path%></li>
<% end %>

Related

How to solve broken routes?

I'm working in a project that has a user to user friendship feature.
I don't know what is happening with my routes, but this is my output in html:
/friends.Friends -> this was supposed to be a link "friends", but when I click on it nothing happens
and
/friend_requests.Friend%20requests -> it was also supposed to be a link "friend_requests"
Rails.application.routes.draw do
root "events#index"
devise_for :users
devise_scope :user do
get "login", :to => "devise/sessions#new"
get "logout", :to => "devise/sessions#destroy"
get "signup", :to => "devise/registrations#new"
end
resources :users, :only => [ :index, :show ]
resources :friendships, :only => [:create, :update, :destroy]
get '/friend_requests', to: 'friend_requests#index'
get '/friends', to: 'friends#index'
resources :events
end
and this is what i did in my view:
<%= link_to friends_path "Friends" %>
<br>
<%= link_to friend_requests_path "Friend requests" %>
This is the output of bundle exec rake routes
Prefix Verb URI Pattern Controller#Action
root GET / events#index
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
user_password PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
POST /users/password(.:format) devise/passwords#create
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
user_registration PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
POST /users(.:format) devise/registrations#create
login GET /login(.:format) devise/sessions#new
logout GET /logout(.:format) devise/sessions#destroy
signup GET /signup(.:format) devise/registrations#new
users GET /users(.:format) users#index
user GET /users/:id(.:format) users#show
friendships POST /friendships(.:format) friendships#create
friendship PATCH /friendships/:id(.:format) friendships#update
PUT /friendships/:id(.:format) friendships#update
DELETE /friendships/:id(.:format) friendships#destroy
friend_requests GET /friend_requests(.:format) friend_requests#index
friends GET /friends(.:format) friends#index
events GET /events(.:format) events#index
POST /events(.:format) events#create
new_event GET /events/new(.:format) events#new
edit_event GET /events/:id/edit(.:format) events#edit
event GET /events/:id(.:format) events#show
PATCH /events/:id(.:format) events#update
PUT /events/:id(.:format) events#update
DELETE /events/:id(.:format) events#destroy
page GET /*id high_voltage/pages#show
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
When I acces by typing localhost:300/friends or localhost:300/friend_requests it works
but when I try to use link to, it's broken :/
The order of your arguments is not correct.
From the Docs
link_to(name = nil, options = nil, html_options = nil, &block) public
Creates an anchor element of the given name using a URL created by the set of options. See the valid options in the documentation for url_for. It’s also possible to pass a String instead of an options hash, which generates an anchor element that uses the value of the String as the href for the link. Using a :back Symbol instead of an options hash will generate a link to the referrer (a JavaScript back link will be used in place of a referrer if none exists). If nil is passed as the name the value of the link itself will become the name.
The name should be passed as first argument but you are passing it as second.
Try to swap the arguments like this:
<%= link_to "Friends" ,friends_path %>
<br>
<%= link_to "Friend requests", friend_requests_path %>
Your link_to helper in the view is not ok,
link_to(name = nil, options = nil, html_options = nil, &block)
<%= link_to "Friends", friends_path %>
<br>
<%= link_to "Friend requests", friend_requests_path %>

Getting error Couldn't find User with 'id'=id

I am learning ruby on rails by making a project web app,
whenever i go to <%= link_to 'My Profile', user_path(:id) %> error Couldn't find User with 'id'=id" is shown...and url is "http://localhost:3000/users/id
If i convert above link to <%= link_to 'My Profile', user_path %>, it works but now all other pages except user's show page give error No route matches {:action=>"show", :controller=>"users"} missing required keys: [:id]....I cant seem to find any solution anywhere...
Here are my configs:
rake routes Prefix Verb URI Pattern Controller#Action
root GET / static#landing
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
user_confirmation POST /users/confirmation(.:format) devise/confirmations#create
new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new
GET /users/confirmation(.:format) devise/confirmations#show
user GET /users/:id(.:format) users#show
_header.html.erb
<%= link_to 'My Profile', user_path %>
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
end
routes.rb
Rails.application.routes.draw do
root 'static#landing'
devise_for :users
resources :users, :only => [:show]
You need to pass the id of a user to user_path, not the symbol :id - so something like
<%= link_to 'My Profile', user_path(#current_user.id) %>
if the user you want to link to is in an instance variable - or since you are using Devise and it provides the current_user helper you might be wanting
<%= link_to 'My Profile', user_path(current_user.id) %>
I think the first thing wrong is this:
<%= link_to 'My Profile', user_path(:id) %>
You are using a symbol, not a variable
<%= link_to 'My Profile', user_path(#id) %>
Would have an actual variable, assuming you have set #id in your controller.
Normally however you would not set the id for a user in a path - it's a recipe for someone to just change the number manually and view someone elses.
Lets assume you set a session variable called :user_id, then you should do something adding a collection route - so no id is sent.
resources :users do
get :show_profile, on: :collection
end
This gets you a path to your show_profile action, called with
link_to 'My Profile', show_profile_user_path
Then in your controller do your user look up from the session - so something like:
#user = User.find_by id: session[:user_id]
I don't know how devises does things, but please don't trust a user to not fiddle with your parameters!

undefined local variable or method with form_tag

I'm trying to create a simple search form in my Rails application. I get an error with the url path of the form:
<%= form_tag(med_search, :method => "get", id: "search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: "Search", class: "form-control" %>
<%= button_to "Search", class: "btn btn-default" %>
<% end %>
The first line above causes error undefined local variable or methodmed_search' for #<#:0x007fab2b5afa90>`
The problem is most likely with my routes setup. I created a new controller action called search so I edited my routes.db to look like this:
resources :meds do
collection do
get 'search' => 'meds#search'
end
end
devise_for :users
#get 'meds/index'
root to: "meds#index"
resources :meds, :path => ''
end
When I do rake routes, I am seeing the path med search so I know the url is valid:
Prefix Verb URI Pattern Controller#Action
med_search GET /meds/:med_id/search(.:format) meds#search
meds GET /meds(.:format) meds#index
POST /meds(.:format) meds#create
new_med GET /meds/new(.:format) meds#new
edit_med GET /meds/:id/edit(.:format) meds#edit
med GET /meds/:id(.:format) meds#show
PATCH /meds/:id(.:format) meds#update
PUT /meds/:id(.:format) meds#update
DELETE /meds/:id(.:format) meds#destroy
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root GET / meds#index
GET / meds#index
POST / meds#create
GET /new(.:format) meds#new
GET /:id/edit(.:format) meds#edit
GET /:id(.:format) meds#show
PATCH /:id(.:format) meds#update
PUT /:id(.:format) meds#update
DELETE /:id(.:format) meds#destroy
What should I change in the routes to fix this?
Thanks!
EDIT: changed url to med_search_path, get new error: No route matches {:action=>"search", :controller=>"meds"} missing required keys: [:med_id]. Looks like it's related to the route /meds/:med_id/search(.:format)
1) you need to change your form_tag like this
<%= form_tag(search_meds_path, :method => "get", id: "search-form") do %>
2) You need to change your route from member to collection like this
resources :meds do
collection do
get 'search' => 'meds#search'
end
end
3) Not sure why you need to add resources :meds, :path => '' at the bottom again. Incase you dont need it, it is better to remove.
It looks like you're trying to code up a search but because you put it in the resources block Rails is assuming you're talking about a specific med.
Remove the route from the resources block and change it to get 'meds/search' => 'meds#search'. That will allow you to use it as just a regular endpoint without Rails complaining that you need an ID.

Rails 4: TypeError no implicit conversion of Symbol into String

I am relatively new to Rails and I encountered what seems to be a common problem but after reading through all the responses, I cannot seem to make any work for my situation.
I have an app that keeps track of loans and users, and am trying to add a payment feature. When I try to reach the payment page I encounter this TypeError: no implicit conversion of Symbol into String. I have tried a bunch of things but nothing seems to work. I'm not sure if its how I am trying to access the loan_id or something else.
The error is encountered in PaymentsController#create
Here is my view:
show.html.erb
<p id="notice"><%= notice %></p>
<div class="row">
<div class="col-md-2">
<ul>
<li><strong>Lender</strong>: <%= #loan.lender.username %></li>
<li><strong>Borrower</strong>: <%= #loan.borrower.username %></li>
<li><strong>Amount Remaining</strong>: <%= #loan.amount %></li>
<li><%= link_to "New Payment", loan_payments_path(#loan.id), :method => :post %></li>
</ul>
<section>
</section>
</div>
</div>
<%= link_to 'Edit', edit_loan_path(#loan) %> |
<%= link_to 'Back', loans_path %>
app/controllers/payments_controller
class PaymentsController < ApplicationController
# POST /loans/:loan_id/payments
def create
#loan = Loan.find(params[:loan_id])
#loan.make_payment(payment)
if #load.save
redirect_to #loan, notice: "Payment successful"
else
redirect_to #loan, alert: "Payment count not be processed"
end
end
private
def payment
require(:loan).require(:payment)[:payment]
end
end
routes
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:index, :show]
resources :loans, shallow: :true do
resources :payments, only: :create
end
root 'static_pages#home'
end
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
users GET /users(.:format) users#index
user GET /users/:id(.:format) users#show
loan_payments POST /loans/:loan_id/payments(.:format) payments#create
loans GET /loans(.:format) loans#index
POST /loans(.:format) loans#create
new_loan GET /loans/new(.:format) loans#new
edit_loan GET /loans/:id/edit(.:format) loans#edit
loan GET /loans/:id(.:format) loans#show
PATCH /loans/:id(.:format) loans#update
PUT /loans/:id(.:format) loans#update
DELETE /loans/:id(.:format) loans#destroy
root GET / static_pages#home
Parameters
{"_method"=>"post",
"authenticity_token"=>"VI7rp4N2eHw+tPkY2noD/so9vnGKy/ue06052Vj1f4qidNzgDjZT3aV5v8+XZMs2ZqiUWE0xzAMSQPWltfT6lg==",
"loan_id"=>"5"}
Your problem in this method:
def payment
require(:loan).permit(:payment)[:payment]
end
Fix it to:
def payment
params.permit(:loan_id)
end
Read how to permit params in Rails.
Update:
Now I get the error ActionController::ParameterMissing in
PaymentsController#create param is missing or the value is empty:
loan
this is normal behavior, because your parameters is empty, you sent nothing to the action, except a load_id, to send the params with #load attributes, pass it to the loan_payments_path() helper, like:
<li><%= link_to "New Payment", loan_payments_path(#loan.id, params: { loan_amount: #loan.amount }), :method => :post %></li>
And permit it in controller code:
def payment
params.permit(:loan_id, :loan_amount)
end

Logout Error: No route matches [GET] "/users/sign_out"

This error has been driving me and a fellow dev insane. We're building an app with Ruby/Rails jazz, and whenever I click to logout for a user session, I get this error:
Routing Error
No route matches [GET] "/users/sign_out"
Try running rake routes for more information on available routes.
Now I've ran rake routes a ton, and I get:
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root / home#index
about /about(.:format) home#about
Is there anything to be done here? I've also followed the answers of a lot of the posts here on Stack Overflow to no avail. Anything else I can test to try to fix this problem?
EDIT: Here is logout link code
<a href="/users/sign_out" class="header-links right-link" data-method="delete" rel="nofollow">Logout</a
Inspect you HTML and make sure rails.js is loaded, and there are no javascript errors. And if you are using jQuery, make sure that there is noConflict.
Note: My guess is you are running rails version < 3.1, So check if these two lines are present in your layout
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
Try:
<%= link_to "Logout", destroy_user_session_path, method: :delete %>
does your routes have this under "devise_for"? :
get 'users/sign_out' => 'sessions#destroy', :as => :destroy_user_session
And try this as link:
<%= link_to "Logout", destroy_user_session_path, method => :delete %>
Check to see if your routes.rb has,
devise_for :users, ActiveAdmin::Devise.config
Sometimes my installs seem to miss this part ActiveAdmin::Devise.configand then I get this error.
I see it in the gem's generator but sometimes it doesn't get added on my apps.

Resources