Rails 3 + Devise - How to get nested resources / routes to work? - ruby-on-rails

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

Related

Conflicting Devise and restful controller routes | Rails 5.2

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'
}

How can I access the profiles/show.html.erb in rails app

I´m using Devise, and after signing up, I want my users to access the profiles/show.html.erb
I have an registrations_controller.rb and in there I have this piece of code
def after_sign_up_path_for(resource)
new_user_profile_path(current_user)
end
It directs the user to profiles/new.html.erb but I want the user to go to profiles/show.html.erb
the rake routesshows this paths:
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
how would I modify this chunk of code to direct to the profiles/show.html.erb?
I'm to unexperienced to figure this out by my self, any help would be greate
this is my routes.rbfile
Rails.application.routes.draw do
devise_for :users, :controllers => { registrations: 'registrations' }
resources :users do
resource :profile
end
root 'pages#index'
end
** Edit**
the rake routes output
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) 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
PATCH /users(.:format) registrations#update
PUT /users(.:format) registrations#update
DELETE /users(.:format) 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
PATCH /users/:user_id/profile(.:format) profiles#update
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
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
GET /%20/users/:user_id/profile(.:format)%20 profiles#show
root GET / pages#index
I fixed it, check your github.
Spelling of your resource is wrong
It should be resources :profile not resource :profile
that is why it was not showing you the paths to the profile resources through rake routes command.
I used the profile_path(current_user) in the show action at profile_controller.rb file
In your controller you need to create
def show
end
You can also try replacing your code in registration controller with.
def after_sign_up_path_for(resource)
show_user_profile_path(current_user)
end
remove 'do' from resources :users do in routes.rb file.
def after_sign_up_path_for(resource)
user_path(current_user)
end
rake routes shows user GET /users/:id(.:format) users#show
routes.rb
get 'profiles/show', to: 'profiles/show', as: :profile
profiles_controller.rb
def show
unless params[:user_id] #user = User.find(current_user.id)
#user = User.find(params[:user_id])
end
and then
def after_sign_up_path_for(resource)
profile_path
end

Devise routing issues with admin role

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.

Rails 3.2.1: link works on app, is present in routes.rb but doesn't show up on rake routes output

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....

User Profile Controller Rspec Test Fails due to route

I'm having a problem testing my new user profile page with Rspec. It's working through the browser, but Rspec is blowing up.
I'm using devise with a separate controller for editing profile fields.
This is a request spec.
it 'Shows the user profile with their non-private data' do
visit user_path(#user)
page.should have_content #user.full_name
end
Fails with this error:
Failure/Error: visit user_path(#user)
ActionController::RoutingError:
No route matches {:action=>"show", :controller=>"users"}
I disagree
#routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
resources :users, :only => [:edit, :update, :show]
The update and edit path helpers are working just fine.
The controller action:
class UsersController < ApplicationController
layout 'profile', :except => [:show]
#... edit and update omitted
def show
#user = User.find(params[:id])
end
end
rake routes shows:
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
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
So it doesn't really look like devise is interfering with my route, and more importantly, everything works in the browser. What am I missing here?
I also tried making a member action called profile instead of the default show, that had the same result
The problem here was I started a new context block and didn't set up #user before the it block. The route thing was just a red herring.
Also proof that you should walk away from your code for awhile if you can't figure things out.

Resources