calf
calf

Reputation: 881

current_user helper returning error in view

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

Answers (1)

Peter Goldstein
Peter Goldstein

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

Related Questions