Reputation: 881
I'm using Devise and in my show view I have:
<%= link_to "Profile", current_user %>
When accessing the view, I get the error:
No route matches {:controller=>"users", :action=>"show"} missing required keys: [:id]
My show method (suggested by a very helpful SO member):
def show
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
end
My 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 :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/edit'
Any ideas why the current_user helper is returning the error?
Upvotes: 0
Views: 944
Reputation: 4545
You're getting this error when you access the view as an unauthenticated visitor because the current_user is nil and there is no route corresponding to user_path(nil). The easiest fix, although not necessarily one I'd recommend, is to change this line in config/routes.rb:
get '', to: 'users#show', as: 'user'
to
get 'profile', to: 'users#show', as: 'profile'
and then update the view to
<%= link_to "Profile", (current_user ? user_path(current_user) : profile_path) %>
A more complex (but in my opinion architecturally superior option) is to pull all of the no-id logic out of your users controller into a profile controller that has an index method like:
class ProfileController
before_filter :check_authentication, only: [:index]
def check_authentication
unless current_user
flash[:notice] = "This page is not available"
redirect_to root_path
end
end
def index
@user = current_user
render 'users/show'
end
end
and then you'd add a matching route and update your link to point to this action.
The users show method you've written essentially ignores the params[:id], which means it's really not a show method. It ALWAYS shows the page for the current_user, regardless of which id is passed in. This ProfileController reflects that.
Then the users show method becomes a bare-bones show method again that just looks up by id, which is what it's supposed to do.
Upvotes: 2