Search code examples
ruby-on-rails-4devisecancan

Rails alias_method to current_user for two user models (Devise, CanCan)


I am using Devise with two user types, Employer and Candidate which are largely different from each other. There is no STI, and one model + Devise authentication for each, currently. When implementing CanCan for authorization, I found that an alias of current_candidate or current_employer to current_user was needed. It appears that only one alias can be used to current_user so the non aliased user type cannot be authorized for any actions.

class ApplicationController < ActionController::Base
  alias_method :current_user, :current_candidate
  #alias_method :current_user, :current_employer
  #^ can't use both simultaneously!
end

The above trips up authorization of employer actions since only the current_candidate can be aliased to current_user which is used in CanCan's current_ability method.

def current_ability
  @current_ability ||= ::Ability.new(current_user)
end

Is there a way to effectively alias both user types to current_user for CanCan? Or is there some type of before method that can set current_user without the alias? Happy to add more code if needed.


Solution

  • You could define the current_user method yourself. It could, for example, go in ApplicationController:

    def current_user
      if current_candidate    # You could use candidate_signed_in? instead.
        current_candidate
      else
        current_employer
      end
    end
    

    Then it should be available in all your controllers and will be used by CanCan's current_ability method. If you want it available in views too, one option is to then add the line helper_method :current_user to ApplicationController.

    Another option is to override the CanCan current_ability method to give the same effect as the above code by adding this to your ApplicationController:

    def current_ability
      @current_ability ||= ::Ability.new((candidate_signed_in?) ? currrent_candidate : current_employer)
    end