Search code examples
ruby-on-railsdevisenamespacesruby-on-rails-5rails-routing

Undefined local variable or method 'current_user' for Namespaced Controller


I'm using Devise along with CanCan/Rolify for authentication for my rails app and I'm having a hard time understanding how to pass Devise methods to namespaced controllers.

I'm using a standard users model and controller for the main part of my app, everything on that side works well and good. However, I have set it up that if an account with a specific role (which is determined after registration) logs in using the main login page, it will redirect them to namespaced views and controllers.

Lets say that user_id: 3 logs in and is redirected to 0.0.0.0/external/dashboard, I can call Devise's current_user method on the dashboard page after redirection and returns the correct information. However, when I set a link_to for that user to be able to edit his profile at 0.0.0.0/external/users/3/edit I receive the following error:

Started GET "/external/users/3/edit" for 127.0.0.1 at 2017-08-31 21:40:59 -0400

ActionController::RoutingError (undefined local variable or method `current_user' for External::UsersController:Class)

routes

devise_for :users, controllers: { confirmations: 'confirmations', registrations: 'registrations' }

# External routes
namespace :external do
  resources :properties, :clients, :orders, :deeds, :mortgages, :users, :owners, :dashboard
end

external/dashboard view

<%= user_name_helper(current_user) %>

user_name_helper (produces user edit link)

def user_name_helper(user)
  if user.name.blank?
    link_to "Update your profile here.", edit_external_user_path(user)
  else
    "Hello, #{user.name}"
  end
end

Error happens when I click the link produced by this helper.

But <%= link_to fa_icon("sign-out", text: "Logout"), destroy_user_session_path, method: :delete %> works fine from 0.0.0.0/external/dashboard.

So I am confused as to why I can call current_user within the view for the External::DashboardController but can't call it within the External::UsersController. All namespaced controllers inherit directly from ApplicationController and I want to keep only using a single users model. I've searched through a bunch of different articles but can't seem to find an answer with a configuration similar to mine, so can anyone explain to me what I might be doing wrong and how to get this to work as well as allowing me to have the ability to use any other Devise methods in my namespaced views? Thanks in advance.


Solution

  • Welp, I figured it out. The issue was that I was calling a conditional before_filter in my external/ controllers as follows:

    before_filter :client_only unless current_user.has_role? :admin
    

    Once I removed that everything worked as intended. I still have the following before_filter in place which works.

    before_filter :client_only
    
    ...
    
    private
    
    def client_only
      redirect_to root_path unless current_user.is_client?
    end 
    

    Not entirely sure why the conditional filter wouldn't work the way I originally had it so if anyone has any insight and feels like sharing then I'm all ears, thanks.