Search code examples
ruby-on-railscancan

Allow access to different views and routes with cancancan?


I'm managing user and admin roles with cancan. I want the user to have access to certain views ("Cursos", "Credenciales", ) but cancan does not allow it. How can I give them access? So, what is happening is that it tries to access the route but goes back to the root as I specified it to do it in the application controller. (Of course it is supposed to access to the controller through that route.) Thanks for your help!!

index.html.erb

<% if current_user %>
  <% if can? :new, @user %>
    <% if can? :new, @empleado  %>
      <li><%= link_to "Lista de Empleados", empleados_path %></li>
      <li> <%= link_to "Agregar Empleado", new_empleado_path %></li>
    <% end %>
  <% end %>      
  <li><%= link_to "Cursos", cursovence_path %></li>
  <li><%= link_to "Credenciales", credencialvence_path %></li>
<% end %>

ability.rb

include CanCan::Ability
def initialize(user)
  user ||= User.new 
  if user.admin?
    can :manage, :all
  else
    can :read, :all
    can :display, :all
  end
end

routes.rb

devise_for :users 
root 'empleados#index'
resources :empleados
resources :users
post '/empleados/:id' => 'empleados#display'
get '/cursovence' => 'empleados#indexCursoVence'
get '/credencialvence' => 'empleados#indexCredencialVence'
get '/proxvacas' => 'empleados#indexProxVacas'

empleados_controller.rb

class EmpleadosController < ApplicationController
  before_action :authenticate_user!
  # load_and_authorize_resource - It did not work with this validation
  load_resource  #So, I changed it for only this one

  def index
   ....
  end      

  def new
   ....
  end    

end                                                 

application_controller.rb

class ApplicationController < ActionController::Base
   protect_from_forgery with: :exception
   rescue_from CanCan::AccessDenied do |exception|
       flash[:error] = "Access denied."
       redirect_to root_url
   end
end

Solution

  • In cancan you can assign abilities based on symbols not classes (in case you don't have models to base your abilities on) https://github.com/ryanb/cancan/wiki/Non-RESTful-Controllers

    So in your view check for can? :index, :cursos and can? :index, :credenciales given that you added can :read, :all in your ability

    <% if can? :index, :cursos %>
      <li><%= link_to "Cursos", cursovence_path %></li>
    <% end %>
    <% if can? :index, :credenciales %>
      <li><%= link_to "Credenciales", credencialvence_path %></li>
    <% end %>