Devise : overriding the devise routes and controllers at the same time - ruby-on-rails

i want to ovverride my devise routes and the sessions controller from this gem at the same time. How do i do this ?
I thought about :
devise_for :admins, :skip => [:sessions],
controllers: { sessions: "admins/sessions" }
devise_scope :admin do
get 'login' => 'devise/sessions#new', :as => :new_admin_session
post 'login' => 'devise/sessions#create', :as => :admin_session
delete 'logout' => 'devise/sessions#destroy', :as => :destroy_admin_session
end
but my paths are chaging but the controller - not. How can I implement this right ?

When you specify controllers: { sessions: "admins/sessions" }, that implies that you have a file called sessions_controller.rb in this path: app/controllers/admins/sessions_controller.rb, and that it starts with:
module Admins
class SessionsController < Devise::SessionsController
If this is the controller you want your app to use, then in the devise_scope block, you must tell it to use admins/sessions, not devise/sessions, like this:
devise_scope :admin do
get 'login' => 'admins/sessions#new', :as => :new_admin_session
post 'login' => 'admins/sessions#create', :as => :admin_session
delete 'logout' => 'admins/sessions#destroy', :as => :destroy_admin_session
end

What about something like:
devise_for :admin, exclude: [:sessions] do
get '/login', to: 'sessions#new', as: :new_admin_session
post '/login', to: 'sessions#create', as: :admin_session
delete '/logout', to: 'sessions#destroy', as: :destroy_admin_session
end

Related

Change default routes Devise Rails

I have this routes.rb:
devise_for :users, :path => '', path_names:
{ sign_in: "login", sign_out: "logout", sign_up: "registration"}
I changed sign_in and sign_up routes and if you go to sign_up you will get 404 error, instead /registration will work. What I want is to change and add other routes like forgotten password in the same way.
If I type in the console rake routes, I see this for forgotten password:
new_user_password GET /password/new(.:format) devise/passwords#new
How can add the additional routes in a way that my custom defined route will work, but not the default?
Be sure to checkout the ActionDispatch::Routing::Mapper#devise_for documentation here.
You can just simply do something like this-
devise_for :users, path: 'auth', path_names: { sign_in: 'login',
sign_out: 'logout',
password: 'secret',
confirmation: 'verification',
unlock: 'unblock',
registration: 'register',
sign_up: 'cmon_let_me_in' }
Here is an example for the sessions, registrations, and passwords controller actions/routes:
devise_for :users, skip: [:sessions, :registrations, :passwords]
devise_scope :user do
# sessions
get 'login', to: 'devise/sessions#new', as: :new_user_session
post 'login', to: 'devise/sessions#create', as: :user_session
delete 'logout', to: 'devise/sessions#destroy', as: :destroy_user_session
# registrations
put '/account', to: 'devise/registrations#update'
delete '/account', to: 'devise/registrations#destroy'
post '/account', to: 'devise/registrations#create'
get '/register', to: 'devise/registrations#new', as: :new_user_registration
get '/account', to: 'devise/registrations#edit', as: :edit_user_registration
patch '/account', to: 'devise/registrations#update', as: :user_registration
get '/account/cancel', to: 'devise/registrations#cancel', as: :cancel_user_registration# passwords
# passwords
get 'new-pass', to: 'devise/passwords#new', as: :new_user_password
get 'edit-pass', to: 'devise/passwords#edit', as: :edit_user_password
patch 'edit-pass', to: 'devise/passwords#update', as: :user_password
post 'new-pass', to: 'devise/passwords#create', as: :user_password
end
As seen in the 4th code sample block in this wiki
You need to skip passwords and rebuild its routes as you want,
devise_for :users, skip: [:passwords]
devise_scope :user do
match '/forgotten-password' => 'devise/passwords#create', as: :user_password, via: [:post]
match '/forgotten-password' => 'devise/passwords#update', via: [:put, :patch]
get 'forgotten-password', to: 'devise/passwords#new', as: :new_user_password
end
Your custom routes will work. And it skip all routes in that modules.
NOTE : You need to overwrite all remaining routes of that module as you want.

Class level method "undefined"

With the code below:
class TestController < ApplicationController
wrap_parameters :test, format: [:json, :xml], include: self.test_method
def self.test_method
[ :one, :two, :three ]
end
end
I get a RoutingError:
ActionController::RoutingError (undefined method 'test_method' for TestController:Class)
I tried a number of different derivations of this, but nothing is working.
EDIT: routes.rb -- was routing to api.servername/create during error:
TestApp::Application.routes.draw do
resources :subscriptions
# API subdomain
constraints subdomain: 'api' do
get '/' => 'test#index'
post '/create', to: 'test#create'
get '/status', to: 'test#show'
end
# root route
root to: 'pages#index'
# User routes
devise_scope :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
get 'register' => 'devise/registrations#new', :as => :new_user_registration
get 'profile' => 'devise/registrations#edit', :as => :edit_user_registration
get 'users' => 'users/registrations#index'
end
devise_for :users, :skip => [:sessions], controllers: { registrations: 'users/registrations' }
end

how to use new_user_session route from devise as the root path?

Problem - I don't know how to set the new_user_session route from devise gem as the root path in Rails app.
Rails.application.routes.draw do
devise_for :users
resources :dashboard
root to: "home#index"
Place this line in routes.rb
devise_scope :user do
root :to => 'devise/sessions#new'
end
You need to set default session route.
Replace with .
devise_for :users, :controllers => {:registrations => "registrations", :sessions => "sessions"}
devise_for :users do
get '/users/sign_in', :to => 'devise/sessions#new', :as => :new_user_session
get '/users/sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
end
and root to
devise_scope :user do
get "/" => "sessions#new"
end

Making the show page url at the site root after logging in

Currently, when a user logs in or signs up, they are redirected to /users/1, for example, as their show page.
I can't figure out what routes to use to redirect them to just the site root (example.com, for example, instead of example.com/users/1). The logged in site root would be the show page, the logged out site root would be the normal site home page.
I'm using devise, if it matters.
Current routes:
devise_for :users, :path => '', :path_names => { :sign_in => 'login', :sign_out => 'logout',
:password => 'password', :confirmation => 'verification',
:unlock => 'unblock', :registration => 'signup',
:sign_up => 'new' }
devise_scope :user do
get 'login', to: 'devise/sessions#new'
get 'users/login', to: 'devise/sessions#new'
get 'logout', to: 'devise/sessions#destroy'
get 'signup', to: 'devise/registrations#new'
get 'password', to: 'devise/passwords#new'
match 'users/secret', to: "devise/passwords#create", via: :post
match 'sessions/user', to: 'devise/sessions#create', via: :post
match 'users/signup', to: 'devise/registrations#create', via: :post
match 'users/signup', to: 'devise/registrations#create', via: :post
end
resources :users
resources :sessions
root 'site#index'
Updated Routes:
devise_for :users, :path => '', :path_names => { :sign_in => 'login', :sign_out => 'logout',
:password => 'password', :confirmation => 'verification',
:unlock => 'unblock', :registration => 'signup',
:sign_up => 'new' }
get 'login' => 'users/login'
devise_scope :user do
get 'login', to: 'devise/sessions#new'
get 'users/login', to: 'devise/sessions#new'
get 'logout', to: 'devise/sessions#destroy'
get 'signup', to: 'devise/registrations#new'
get 'password', to: 'devise/passwords#new'
match 'users/secret', to: "devise/passwords#create", via: :post
match 'sessions/user', to: 'devise/sessions#create', via: :post
match 'users/signup', to: 'devise/registrations#create', via: :post
match 'users/signup', to: 'devise/registrations#create', via: :post
end
get '', to: 'users#show', as: 'user'
get 'edit', to: 'users#edit', as: 'user/edit'
#resources :users
resources :sessions
# Authenticated Users:
authenticated :user do
root to: "users#show", as: :authenticated_root
end
# Non-Authenticated Users
root to: 'site#index'
You can use authenticated and unauthenticated resources.
Like this:
authenticated :user do
root to: "users#show", as: :authenticated_root, via: :get
end
unauthenticated do
root 'site#index'
end
Then in your users controller you'll need to make sure to check for the devise helper current_user instead of the id because you aren't passing one.
like
if params[:id]
#user = User.find params[:id]
else
#user = current_user
end
If you don't want users to be able to access this route, its easier to manage in the controller. Just modify the if statement, something like
if params[:id]
if current_user
#user = current_user
else
flash[:notice] = "This page is not available"
redirect_to root_path
end
else
#user = current_user
end
Updated routes:
devise_for :users, :path => '', :path_names => { :sign_in => 'login', :sign_out => 'logout',
:password => 'password', :confirmation => 'verification',
:unlock => 'unblock', :registration => 'signup',
:sign_up => 'new' }
get 'login' => 'users/login'
devise_scope :user do
get 'login', to: 'devise/sessions#new'
get 'users/login', to: 'devise/sessions#new'
get 'logout', to: 'devise/sessions#destroy'
get 'signup', to: 'devise/registrations#new'
get 'password', to: 'devise/passwords#new'
match 'users/secret', to: "devise/passwords#create", via: :post
match 'sessions/user', to: 'devise/sessions#create', via: :post
match 'users/signup', to: 'devise/registrations#create', via: :post
match 'users/signup', to: 'devise/registrations#create', via: :post
end
#resources :users
resources :sessions
# Authenticated Users:
authenticated :user do
root to: "users#show", as: :authenticated_root
end
# Non-Authenticated Users
root to: 'site#index'
get '', to: 'users#show', as: 'user'
get 'edit', to: 'users#edit' as: 'user'
In your routes.rb (change the destination to: to the pages you wish)
YourApp::Application.routes.draw do
...
# Authenticated Users:
authenticated :user do
root to: 'user#show', as: :authenticated_root
end
# Non-Authenticated Users
root to: 'site#index'
end
Rails 4 Fix: https://github.com/plataformatec/devise/issues/2393#issuecomment-17298414
In UserController.rb: Make sure in your show method, that you use current_user instead of params[:id]. You do this because typically whenever you call your show action you send it an id, however in this case, you're not going to be doing so.
class UsersController < ApplicationController
def show
if params[:id].present?
#user = User.find(params[:id])
else
#user = current_user
end
end
end

Devise - Changing the name of a routing

By default Devise creates a routing for a sign-in as '/sign_in'.
How would I change the path so that it is '/log_in'?
By adding scope
devise_for :users
devise_scope :user do
get '/login' => 'devise/sessions#new'
get '/logout' => 'devise/sessions#destroy'
end
This is how I did it in the end, given that I was already inserting controllers to handle aspects of Devise:
in routes.rb
#Add Devise authentication to users, handling omniauth callbacks in users/omniauth_callbacks_controller
devise_for :users, :skip => [:sessions],
:controllers => { :omniauth_callbacks => 'users/omniauth_callbacks',
:registrations => 'users/registrations'
}
# :skip => [:sessions] tells devise not to create routes for sessions, allowing us to declare our own
as :user do
get 'users/log_in' => 'devise/sessions#new', :as => :new_user_session
post 'users/log_in' => 'devise/sessions#create', :as => :user_session
delete 'users/log_out' => 'devise/sessions#destroy', :as => :destroy_user_session
end

Resources