using multiple "root to" with 2 devise models - ruby-on-rails

I have 2 devise models which is fine as they capture different values and i felt separating them was the best solution instead of using roles.
That being said, I am trying to root to different views. Here is my routes file:
devise_for :patients, controllers: {
sessions: 'patients/sessions',
registrations: 'patients/registrations'
}
as :patient do
authenticated do
root to: 'dashboard#patient'
end
unauthenticated do
root to: 'shared#home', as: 'unauthenticated_root'
end
end
devise_for :pharmacists, controllers: {
sessions: 'pharmacists/sessions',
registrations: 'pharmacists/registrations'
}
as :pharmacist do
authenticated do
root to: 'dashboard#pharmacist'
end
unauthenticated do
root to: 'shared#home', as: 'unauthenticated_root'
end
end
This is the error message:
Invalid route name, already in use: 'root'
You may have defined two routes with the same name using the `:as` option,
or you may be overriding a route already defined by a resource with the
same naming.
What would be the best way to alleviate this issue ?

You can achieve the same thing using the below hacks without the devise_scope
authenticated :patient do
root to: "patients#show", as: :authenticated_patient
end
authenticated :pharmacist do
root "pharmacists#index", as: :authenticated_pharmacist
end
unauthenticated do
root "pages#home", as: :unauthenticated_user
end

The issue stems from the fact that i was not using "as:" on the actual roots so they end up having the same endpoints. after fixing this issue the correct code looks like this:
devise_for :patients, controllers: {
sessions: 'patients/sessions',
registrations: 'patients/registrations'
}
devise_scope :patient do
authenticated do
root to: 'dashboard#patient', as: 'authenticated_patient_root'
end
unauthenticated do
root to: 'shared#home', as: 'unauthenticated_patient_root'
end
end
devise_for :pharmacists, controllers: {
sessions: 'pharmacists/sessions',
registrations: 'pharamacists/registrations'
}
devise_scope :pharmacist do
authenticated do
root to: 'dashboard#pharmacist', as: 'authenticated_pharmacist_root'
end
unauthenticated do
root to: 'shared#home', as: 'unauthenticated_pharmacist_root'
end
end

Related

Rails Devise, how to correctly nest resources

Here's my issue, I want to correctly nest my devise routes from :
user_je_session POST /users/jes/:je_id/sign_in(.:format)
to :
user_je_session POST /jes/:je_id/users/sign_in(.:format)
The objective is that my users can have multiple accounts, depending on the "je" they want to access.
there's my actual routes :
root to: 'pages#home'
devise_for :admins, controllers: { sessions: 'admin/sessions', registrations: 'admin/registrations' }
resources :jes, param: :nom do
devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations' }
end
Thanks for your help
I think it's easier to use devise_scope. You can customize the devise routes as you wish. Something like this might be work:
devise_for :admins, controllers: {
sessions: 'admin/sessions',
registrations: 'admin/registrations'
}
as :admin do
# Please change to: value to your actual controller or action
post '/jes/:je_id/users/sign_in', to: 'admin/sessions#create'
end
Please read more on the documentation page.
https://github.com/heartcombo/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes

How to use multiple root route in rails 6?

Just updated to rails 6 and having trouble with a conditional root route
devise_scope :user do
authenticated do
root to: 'users#show'
end
unauthenticated do
root to: 'visitors#index'
end
end
I've attempted to check for the logged-in user in visitors#index and do a redirect to users#show but now I have this ugly URL '/users/:id' instead of being able to visit users#show with a clean root URL.
In my case I was able to solve this by adding an :as argument:
devise_scope :user do
authenticated do
root to: 'users#show'
end
unauthenticated do
root to: 'visitors#index', as: :visitors_url
end
end
I think the reasoning behind the change is to make it so that Rails knows where to route root_url.
Note: I found the answer on reddit where it was suggested using namespace would be cleaner.
namespace :visitors, path: nil do
root to: 'visitors#index'
end
I don't know if there is a way to make that work with devise though.

Logout routing using OAuth and Rails

I'm using OAuth 2 gem to authenticate via google and facebook.
I need to do logout from google and facebook when I logout from my application. In OA documentation said to:
devise_scope :user do
delete 'sign_out', to: 'devise/sessions#destroy', as: :destroy_user_session
end
Add this to routes.rb. I did it so, my routs rb now looks like:
Rails.application.routes.draw do
devise_for :users, controllers: { omniauth_callbacks: 'callbacks' }
devise_scope :user do
delete 'sign_out', to: 'devise/sessions#destroy', as: :destroy_user_session
end
When I add this line, i got an error when i try to rails s my application:
/Users/damirik/.rvm/gems/ruby-2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/routing/route_set.rb:507:in add_route': Invalid route name, already in use: 'destroy_user_session' (ArgumentError)
You may have defined two routes with the same name using the:as` option, or you may be overriding a route already defined by a resource with the same naming.
I really dont understand how to fix it. Help please
Looking at the devise_for method documentation, I can see that it already adds the exact delete 'sign_out' route, which makes it redundant.
This should be enough to make your code work.
Rails.application.routes.draw do
devise_for :users, controllers: { omniauth_callbacks: 'callbacks' }
end

Rails 4 + Devise: set default root route for authenticated users

I have done some research and seen that this question has already been addressed several times, in different places:
Devise with rails 4 authenticated root route not working
Different '/' root path for users depending if they are authenticated (using devise)
Authenticated Route Constraints
Rails Tip #5: Authenticated Root and Dashboard Routes With Devise
I tried to follow the examples given in the links above and came up with the following solution, in my routes.rb file:
root to: 'pages#home'
devise_for :users, :path => 'account', controllers: { registrations: "registrations", confirmations: "confirmations" }
authenticated :user do
root 'calendars#index', as: :authenticated_root
end
The goal here is to direct unauthenticated users to the regular home page of the website, while authenticated users will go to their dashboard, inside the app, i.e. the calendars#index route, defined as follows in my routes:
calendars GET /calendars(.:format) calendars#index
However, when I log in as a user, and visit http://localhost:3000/, I keep landing on the regular home page of the website, instead of the user's dashboard inside the app.
What am I doing wrong?
Change routes.rb so that the unauthenticated root route is wrapped, just like the authenticated one:
devise_for :users, :path => 'account', controllers: { registrations: "registrations", confirmations: "confirmations" }
authenticated :user do
root 'calendars#index', as: :authenticated_root
end
unauthenticated :user do
root 'pages#home', as: :unauthenticated_root
end

Rails & Devise Mapping Path

I'm receiving the following error when trying to go to http://app.mysite.dev/login -
Could not find devise mapping for path "/login".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
get "/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]
Now, here is the relevant bits of my routes.rb file:
namespace 'app', path: '', constraints: { subdomain: 'app' } do
devise_for :users, :skip => [:registrations, :confirmations]
devise_for :agents, :skip => :sessions
devise_scope :users do
get "login" => "users/sessions#new"
end
...
end
And the route generated by the get "login" line is as follows (from rake routes)
app_login GET /login(.:format) app/users/sessions#new {:subdomain=>"app"}
I don't know if it matters, but I'm using STI for Users > Agents relationship.
So, I already am defining the scope for devise, and I'm not testing, so any ideas what's going on?
Try to replace your devise_scope with the following instead. Within your namespace 'app' block.
devise_scope :app_user do
get "login" => "users/sessions#new"
end
It appears to be devise was changing the scope it was looking for within a namespace.
For your reference:
https://github.com/plataformatec/devise/issues/2496
And yeah, it should be devise_scope :app_user instead of devise_scope :app_users
It's just a simple typo - devise_scope :users should be devise_scope :user, as stated in the error message.
It seems you didn't define a custom SessionsControllerfor your :users, and Devise cannot use it's default one since you namespaced your devise_scope :users.
I'd define your own custom class App::SessionsController and then add it rewrite your routes like this:
namespace 'app', path: '', constraints: { subdomain: 'app' } do
devise_for :users, controllers: { sessions: 'sessions' }, skip: [:registrations, :confirmations]
devise_scope :users do
get "login" => "sessions#new"
end
end

Resources