You are being redirected. Rails 5 + Devise - ruby-on-rails

My rails application successfully logs out a user and redirects to the about page when in development mode. But the moment i deploy it to production it returns a 302 status and a page that shows "you are being redirected". Am using devise for authentication below is what my code actually looks like.
The routes
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: "users/registrations", confirmations: "users/confirmations", sessions: "devise/sessions" }, skip: [:sessions]
devise_scope :user do
get "login" => "devise/sessions#new", as: :new_user_session
post "login" => "devise/sessions#create", as: :user_session
get "/join" => "users/registrations#new", as: :join
get '/logout', to: "devise/sessions#destroy", as: :destroy_user_session
end
resources :companies
get "/about", to: "pages#about"
get "/faq", to: "pages#faq"
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'pages#home'
end
My application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
protected
def after_sign_in_path_for(resource)
company_path(resource)
end
def after_sign_out_path_for(resource_or_scope)
"/about"
end
def store_location
session[:return_to] == request.full_path
end
def clear_stored_location
session[:return_to] = nil
end
def redirect_back_or_to(alternate)
redirect_to(session[:return_to] || alternate)
clear_stored_location
end
end
And finally my link to log out.
<%= link_to "Log out", destroy_user_session_path %>
Please note that i am using devise 4.2.0 and capistrano for deployment.
Regards
~

I had to override devise sessions#controller and changed my routes to:
delete 'logout', to: "users/sessions#destroy", as: :destroy_user_session
Then i added delete method to my link for logging out.

Related

Cannot rake migration for my ruby project

When I try to rake a migration for my ruby project, it gives me an error "'API::sessions' is not a supported controller name". Does anyone know how to solve this problem? The following code is from my routes.rb file and sessions_controller.rb file.
Rails.application.routes.draw do
get 'projects/:id', to: 'projects#show'
get 'projects', to: 'projects#index'
get 'welcome/index'
root 'welcome#index'
match '/login', to: 'sessions#new', via: :get
match '/login_create', to: 'sessions#create', via: :post
resources :users
scope :format => true, :constraints => { :format => 'json' } do
post "/api/login" => "API::sessions#create"
delete "/api/logout" => "API::sessions#destroy"
end
end
class API::SessionsController < API::ApiController
skip_before_action :require_login, only: [:create], raise: false
def create
if user = User.valid_login?(params[:email], params[:password])
allow_token_to_be_used_only_once_for(user)
send_auth_token_for_valid_login_of(user)
else
render_unauthorized("Error with your login or password")
end
end
def destroy
logout
head :ok
end
private
def send_auth_token_for_valid_login_of(user)
render json: { token: user.token }
end
def allow_token_to_be_used_only_once_for(user)
user.regenerate_token
end
def logout
current_user.invalidate_token
end
end
The error appears when you define the post and delete routes within the format scope, to tell Rails which controller and action/method use for the URI being defined.
To refer then the controller name and action use the lowercase name followed by a slash, instead the uppercase controller name and colons ::, like:
post '/api/login' => 'api/sessions#create'
delete '/api/logout' => 'api/sessions#destroy'

No route matches for devise sessions destroy path

I have installed devise to my rails app and was originally able to sign out using <%= link_to('Logout', destroy_user_session_path) %>
However, somewhere along the line after adding more code and a few gems (paperclip, act_as_votable, social_share_button) I was not able to use the same link. When I click the link_to I receive the error
No route matches [GET] "/users/sign_out"
I have also tried adding config.sign_out_via = :get to my devise.rb file but still got the same error. What have I done wrong?
routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'users/registrations', sessions: 'users/sessions' }
root to:'ideas#index'
get "/page", to: 'pages#index'
resources :ideas, only: [:index, :show, :create, :destroy, :new] do
member do
put "like", to: "ideas#upvote"
put "dislike", to: "ideas#downvote"
end
end
resources :comments, only: [:create]
end
sessions controller
class Users::SessionsController < Devise::SessionsController
def new
super
end
def create
super
end
def destroy
super
end
end
I believe <%= link_to 'Logout', destroy_user_session_path, method: :delete %> is what you're looking for

No Route Matches ... Rails Engine

So I keep getting the error:
No route matches {:action=>"create", :controller=>"xaaron/api_keys"}
Which is thrown in the test:
it "should not create an api key for those not logged in" do
post :create
expect(response).to redirect_to xaaron.login_path
end
when I go to spec/dummy and run the rake routes command I see:
api_keys GET /api_keys(.:format) xaaron/api_keys#index
POST /api_keys(.:format) xaaron/api_keys#create
new_api_key GET /api_keys/new(.:format) xaaron/api_keys#new
edit_api_key GET /api_keys/:id/edit(.:format) xaaron/api_keys#edit
api_key GET /api_keys/:id(.:format) xaaron/api_keys#show
PATCH /api_keys/:id(.:format) xaaron/api_keys#update
PUT /api_keys/:id(.:format) xaaron/api_keys#update
DELETE /api_keys/:id(.:format) xaaron/api_keys#destroy
Which shows that yes this route does exist. My routes file for this engine looks like:
Xaaron::Engine.routes.draw do
get 'login' => 'sessions#new', :as => 'login'
get 'logout' => 'sessions#destroy', :as => 'logout'
get 'signup' => 'users#new', :as => 'signup'
get 'permission_denied' => 'error#denied', :as => 'permission_denied'
get 'record_not_found' => 'error#error', :as => 'record_not_found'
get 'password_reset' => 'password_resets#edit', :as => 'rest_user_password'
resource :error, controller: 'error'
resources :users
resources :api_keys
resources :sessions
resources :roles
resources :password_resets
end
What am I missing?
update
For those of you curious how I am getting these routes, its because the dummy app's routes file is set up (by default) as such:
Rails.application.routes.draw do
mount Xaaron::Engine => "/xaaron"
end
Update II
I have been reading this api docs on how routing is done in engines and I believe the way I have done this is correct, how ever the controller is defined as such:
module Xaaron
class ApiKeysController < ActionController::Base
before_action :authenticate_user!
def index
#api_key = Xaaron::ApiKey.where(:user_id => current_user.id)
end
def create
#api_key = Xaaron::ApiKey.new(:user_id => current_user.id, :api_key => SecureRandom.hex(16))
create_api_key(#api_key)
end
def destroy
Xaaron::ApiKey.find(params[:id]).destroy
flash[:notice] = 'Api Key has been deleted.'
redirect_to xarron.api_keys_path
end
end
end
You need to tell your spec you are using the engine routes:
describe ApiKeysController do
routes { Xaaron::Engine.routes }
it "should not create an api key for those not logged in" do
post :create
expect(response).to redirect_to xaaron.login_path
end
end

Routing Error: uninitialized constant UserFriendshipsController

I am working on a Team Treehouse Ruby on Rails app that emulates a basic Facebook app.
I am now added social feature's like friends.
I recently added the following link to one of my views:
<%= link_to "Add Friend", new_user_friendship_path(friend_id: #user), class: 'btn' %>
When click the resulting button, I get the following error:
Routing Error
uninitialized constant UserFriendshipsController
Try running rake routes for more information on available routes.
I am thinking the problem is in either my "user_friendship_controller.rb" of "config/routes.rb " file.
Here is my "user_friendship_controller.rb file:
class UserFriendshipsController < ApplicationController
before_filter :authenticate_user!, only: [:new]
def new
if params[:friend_id]
#friend = User.where(profile_name: params[:friend_id]).first
#user_friendship = current_user.user_friendships.new(friend: #friend)
else
flash[:error] = "Friend required"
end
rescue ActiveRecord::RecordNotFound
render file: 'public/404', status: :not_found
end
end
And here is my "config/routes" file:
Treebook::Application.routes.draw do
as :user do
get '/register', to: 'devise/registrations#new',via: :get, as: :register
get '/login', to: 'devise/sessions#new', via: :get, as: :login
get '/logout', to: 'devise/sessions#destroy', via: :delete, as: :logout
end
devise_for :users, :skip => [:sessions]
as :user do
get '/login' => 'devise/sessions#new', as: :new_user_session
post '/login' => 'devise/sessions#create', as: :user_session
delete '/logout' => 'devise/sessions#destroy', as: :destroy_user_session
end
resources :user_friendships do
end
resources :statuses
get 'feed', to: 'statuses#index', as: :feed
root to: 'statuses#index'
get '/:id', to: 'profiles#show', as: 'profile'
end
Any help figuring out this bug is a great help.
Thanks
It looks like it's just a simple mis-naming of your file.
Try renaming it to user_friendships_controller.rb. Rails expects your class declaration to match the file name (as it stands it'd be looking for you to define UserFriendshipController).

Setting Devise Login to be root page

I am using the following code for my routes:
devise_for :user,
:as => '',
:path_names => {
:sign_in => "",
:sign_out => "logout",
:sign_up => "register"
}
But when I'm logged out and I goto /logout I get the following error:
No route matches {:action=>"new",
:controller=>"devise/sessions"}
How do I setup the root path to be to :sign_in action?
To follow on from the people who are asking about the error Could not find devise mapping for path "/" there is a workaround.
You'll find that there is a clue in your logs which will probably say:
[Devise] Could not find devise mapping for path "/".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
match "/some/route" => "some_devise_controller"
end
2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
So I retried the approach but instead wrapping it (as #miccet suggets) inside a scope block:
devise_scope :user do
root to: "devise/sessions#new"
end
This worked fine for me
devise_for :users
devise_scope :user do
authenticated :user do
root 'home#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
Just like this, tested on Rails Rails 4.1.0.rc1.
root :to => "devise/sessions#new"
I needed to set the default home root. I felt like I had tried this all night last night (prior to posting the question), but it's working now. If you're logged out, Devise attempts to redirect you to the root path which I had undefined.
(This was posted as a suggested edit, but should have been an answer of its own. I don't know if it makes sense or not. Dear anonymous editor: feel free to repost this answer as your own, and leave me a comment so I'll delete this copy.)
root :to => redirect("/users/login")
I got this to work with #VvDPzZ answer. But I had to modify it slightly
devise_scope :business_owner do
authenticated do
root to: 'pages#dashboard'
end
unauthenticated do
root to: 'devise/sessions#new', as: 'unauthenticated_root'
end
end
I had to ad to: in the root path declaration. I also removed the as: :authenticated_root because I already had some places in my application referencing root_path in links. By leaving out the as: :authenticated_root part I didn't have to change any of my existing links.
I guess you have different user roles. If you do you have to add a scope like this to the users resource:
devise_scope :user do
get "/logout" => "devise/sessions#destroy"
end
You can read more about overriding devise routes here:
https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes
Some of these solutions are way too complex. Just use Rails:
Add 'get' 'users/root', to: 'users#root' to config/routes.rb.
In UsersController do something like:
def root
if user_signed_in?
redirect_to root_for_signed_in_user_path (or whatever)
else
redirect_to new_user_session_path
end
end
Using rails 3.2 and devise 3.2.3 I manage to setup my home page "home#index" (controller#action) as the login page making the following changes.
#1 Added the login form to the home page:
<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>
#2 Added methods resource_name, resource and devise_mapping to app/heldpers/application_helper.rb:
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
#3 Created a custom sessions controller app/controllers/users/sessions_controller.rb:
class Users::SessionsController < Devise::SessionsController
protected
# This method tell sessions#create method to redirect to home#index when login fails.
def auth_options
{ scope: resource_name, recall: 'home#index' }
end
end
#4 Skip the session routes and setup the custom sessions controller in config/routes.rb:
devise_for :users, path: 'auth', skip: [:sessions],
controllers: {
sessions: 'users/sessions'
}
as :user do
get 'auth/sign_in' => 'home#index', as: :new_user_session
post 'auth/sign_in' => 'users/sessions#create', as: :user_session
delete 'auth/sign_out' => 'users/sessions#destroy', as: :destroy_user_session
end
I'm new on rails and I didn't know your 'device_scope' name have to be different to your 'device_for' name. Notice my example.
I tried this a hundred times a this is why it didn't work jajaja
devise_for :user_devises, path: 'user_devises'
devise_scope :user_devise do
authenticated :user_devise do
root 'home#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end

Resources