I'm working on a Rails 5.2 project that uses Devise to manage a User model. I want users to be able to sign themselves up, and allow administrators to create accounts on their behalf. I've set up the User model with Devise, and generated scoped controllers (and views) for the resource. This covers the self-signup aspect, and to cover the administrator-initiated sign-up, I've created a users_controller as a standard restful controller, and in the routes, set up a resources route respectively. This seems to work for everything except the users#create action route conflicts with the route created by the devise_for for users/registrations#create (see generated routes below). This causes users#new form submissions to be incorrectly handled by the Devise users/registrations#create instead of users#create.
What would be the best way of making the *#create routes unique?
routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations' }
resources :users
end
Generated Routes
new_user_session GET /users/sign_in(.:format) users/sessions#new
user_session POST /users/sign_in(.:format) users/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) users/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) users/registrations#cancel
new_user_registration GET /users/sign_up(.:format) users/registrations#new
edit_user_registration GET /users/edit(.:format) users/registrations#edit
user_registration PATCH /users(.:format) users/registrations#update
PUT /users(.:format) users/registrations#update
DELETE /users(.:format) users/registrations#destroy
POST /users(.:format) users/registrations#create
---
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
Something like this
devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations' }
devise_scope :user do
post '/users/create' => 'users#create', as: :create_user
get '/users' => 'users#index', as: :list_users
get '/users/:id' => 'users#show', as: :show_user
end
or you can skip create action while defining resources :users, except: :create and make use of registrations_controller create.
You can configure the devise route to have a distinguishing path (ie. 'auth')
routes.rb
Rails.application.routes.draw do
devise_for :users, path: 'auth', controllers: { sessions: 'users/sessions', registrations: 'users/registrations' }
resources :users
end
You need this:
devise_for :users, path: 'auth', controllers: {
sessions: 'web/users/sessions',
registrations: 'web/users/registrations'
}
Related
I'm building a Rails website, and setting up the devise routes. So far, I have no trouble and everything works. However, since the website is divided between the administration and the visitor place, I would like the user to be able to edit his profile from a path that looks like /admin/users/1/edit and sign in/out from /user/sign_in or user/sign_out (without the admin prefixe).
So far, I managed to do either with or without the prefix, but not both at the same time.
Here is the relevant part of my route file:
devise_for :users, only: %w['session#new session#destroy']
get '/admin' => 'home#admin', as: :admin
authenticate :user do
scope '/admin' do
resource :basics
resources :portfolios
resources :articles
devise_for :users, excepted: %w['sessions#new session#destroy']
end
end
And here is the result of rake routes:
new_user_session GET /admin/users/sign_in(.:format) devise/sessions#new
user_session POST /admin/users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /admin/users/sign_out(.:format) devise/sessions#destroy
new_user_password GET /admin/users/password/new(.:format) devise/passwords#new
edit_user_password GET /admin/users/password/edit(.:format) devise/passwords#edit
user_password PATCH /admin/users/password(.:format) devise/passwords#update
PUT /admin/users/password(.:format) devise/passwords#update
POST /admin/users/password(.:format) devise/passwords#create
cancel_user_registration GET /admin/users/cancel(.:format) devise/registrations#cancel
new_user_registration GET /admin/users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /admin/users/edit(.:format) devise/registrations#edit
user_registration PATCH /admin/users(.:format) devise/registrations#update
PUT /admin/users(.:format) devise/registrations#update
DELETE /admin/users(.:format) devise/registrations#destroy
POST /admin/users(.:format) devise/registrations#create
How can do this?
Thank you in advance
I believe it may just be a typo, but try changing:
devise_for :users, excepted: %w[sessions#new session#destroy]
to:
devise_for :users, except: %w[sessions#new session#destroy]
Im having a problem routing my custom Users controller and devise gem.
When i try to reach http://localhost:3000/users
<%= link_to 'Users', users_path, class: 'navbar-brand' %>
I get error:
Could not find devise mapping for path "/users". 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]
If i run command rake routes i get this output:
Prefix Verb URI Pattern Controller#Action
root GET / static_pages#home
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
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
account_update PATCH /account_update(.:format) users#update
And this are my routes
root 'static_pages#home'
devise_for :users
resources :users
as :user do
patch 'account_update' => 'users#update'
get 'users' => 'users#index'
end
How to tell rails that on /users it should go to controller Users and select index page
You can try something like that,
devise_for :users
devise_scope :user do
end
I'm trying to add Devise to an existing Rails 3.2.16 app.
I have the basics working, but I'd like to create an admin role that is able to edit any user profile without entering a password.
I used the code from Option 2 - Adding an admin attribute in the Devise Wiki "Add An Admin Role" section to set up the admin role.
My routes.rb has this:
devise_for :users, :controllers => { :registrations => :registrations }
scope "/admin" do
resources :users
end
This gives me the following 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
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) registrations#cancel
user_registration POST /users(.:format) registrations#create
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
PUT /users(.:format) registrations#update
DELETE /users(.:format) registrations#destroy
admin_edit_user GET /admin/users/:id/edit(.:format) users/registrations#edit
users GET /admin/users(.:format) users#index
POST /admin/users(.:format) users#create
new_user GET /admin/users/new(.:format) users#new
edit_user GET /admin/users/:id/edit(.:format) users#edit
user GET /admin/users/:id(.:format) users#show
PUT /admin/users/:id(.:format) users#update
DELETE /admin/users/:id(.:format) users#destroy
The user views (devise/registrations/edit, etc) are hooked up correctly and work just fine, but the admin views are all pulled from the users folder (users/edit, etc), which means they bypass Devise.
For instance, my admin user edit form should probably have some variation on this in the form_for:
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
but that code doesn't pull in any of the user data (all form fields are empty). The only way I can get it to show up is with the old code:
<%= form_for #user do |f| %>
Which then uses the update method from my users_controller, NOT from the Devise registrations_controller.
I've tried lots of variations on the routes because that seems to be key, but non of my attempts have worked. Help?
In order for your form_for helper to properly route your request through Devise, you need to declare your admin/users resource routes as Devise routes:
# config/routes.rb
devise_for :users, :controllers => { :registrations => :registrations }
scope "/admin" do
devise_for :users, :controllers => { :registrations => :registrations }
end
You'll continue to retain Devise functionality while being able to utilize the admin namespace for authorization purposes.
I have these urls:
http://localhost:3000/assets
http://localhost:3000/assets/new
http://localhost:3000/assets/34
http://localhost:3000/assets/34/edit
they work in my app.
I have this routes.rb file:
devise_for :users
match "listings/show_notes" => "listings#show_notes", :as => :show_notes
resources :users
resources :listings
resources :assets
authenticated :user do
root :to => "listings#index"
end
#this route is for file downloads
match "assets/get/:id" => "assets#get", :as => :download
resources :admin_dash_board, :only => :index
I have the following output when I type in 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
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
show_notes /listings/show_notes(.:format) listings#show_notes
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
listings GET /listings(.:format) listings#index
POST /listings(.:format) listings#create
new_listing GET /listings/new(.:format) listings#new
edit_listing GET /listings/:id/edit(.:format) listings#edit
listing GET /listings/:id(.:format) listings#show
PUT /listings/:id(.:format) listings#update
DELETE /listings/:id(.:format) listings#destroy
root / listings#index
admin_dash_board_index GET /admin_dash_board(.:format) admin_dash_board#index
As you can see there are no routes for the resource :assets.
Any idea why? Or whats going on?
Thanks
I think I found your answer here and here.
Try to add this line in your application.rb:
config.assets.prefix = "/new_route"
EDIT - also here with some other options to solve the problem....
In my routes.rb file, the only entries I have are:
devise_for :users, :path => "accounts"
resources :users do
resource :profile
end
but when I run "rake routes" I can see that there are still mapped resources for the user i.e new, create, edit, update etc...this is causing a conflict with some of the devise paths such as new_user_registration_path
new_user_session GET /accounts/sign_in(.:format) devise/sessions#new
user_session POST /accounts/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /accounts/sign_out(.:format) devise/sessions#destroy
user_password POST /accounts/password(.:format) devise/passwords#create
new_user_password GET /accounts/password/new(.:format) devise/passwords#new
edit_user_password GET /accounts/password/edit(.:format) devise/passwords#edit
PUT /accounts/password(.:format) devise/passwords#update
cancel_user_registration GET /accounts/cancel(.:format) devise/registrations#cancel
user_registration POST /accounts(.:format) devise/registrations#create
new_user_registration GET /accounts/sign_up(.:format) devise/registrations#new
edit_user_registration GET /accounts/edit(.:format) devise/registrations#edit
PUT /accounts(.:format) devise/registrations#update
DELETE /accounts(.:format) devise/registrations#destroy
user_profile POST /users/:user_id/profile(.:format) profiles#create
new_user_profile GET /users/:user_id/profile/new(.:format) profiles#new
edit_user_profile GET /users/:user_id/profile/edit(.:format) profiles#edit
GET /users/:user_id/profile(.:format) profiles#show
PUT /users/:user_id/profile(.:format) profiles#update
DELETE /users/:user_id/profile(.:format) profiles#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
How can I get rid of the additional user resources which are appearing at the bottom of this output?
If you only wanted, say, index and show, try:
devise_for :users, :path => "accounts", :only => [:index, :show] do
resource :profile
end
The best way to do this would be to define your Devise (not nested) routes using 'devise_for:', and then in a separate block, do
resources :users, :only => :none do
resource :profile
end
Using ':except => :all' stops any non-nested Users routes from being defined and overriding your Devise routes, but it still creates all of your users/3/profile routes. Then add :path => "accounts" to replace users
So your code would look like
devise_for :users, :path => "accounts"
resources :users , :path => "accounts", :only => :none do
resource :profile
end