Search code examples
ruby-on-railsdevisecancan

Unable to autoload constant Role,expected role.rb to define it issue in rails cancan role based authorization


I'm developing a rails app with role based user authorization with the help of cancan documentation. https://github.com/ryanb/cancan/wiki/Role-Based-Authorization I want 3 user levels as Admin ,Manager,Customer in my rails application. So i've created a devise model as Users and added a migration to add the user role to it.So when a user is signed up it stores the users role(whether he is an admin,a manager or a customer). And in my application there are models and controllers for product,delivery,services. And I want to set access levels to each models.

So Admin have access to all models, controllers

Manager have access to Product, Delivery

Customer have access to Services

And i've written the Ability model as follows

class Ability
  include CanCan::Ability

  def initialize(user)

    user ||= User.new # guest user (not logged in)

    if user.roles == "admin"
      can :manage , :all
    elsif user.roles == "manager"
      can :read, Products, Delivery
    elsif user.roles == "customer"
      can :read, Services
    end
end
end

And in my product's show view i've the following code

<% if can? :manage ,@products%>

<h1>Products</h1>

<% @products.each do |product| %>
<p>     <%= product.name%>
<p>         <%= product.price %><br>
<p>    <%= product.qty %><br>

  <%end%>
<%end%>

User model is as follows

class User < ApplicationRecord
  belongs_to :role
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

         ROLES = %i[admin manager customer]

end

Role Model

class ApplicationController < ActionController::Base

end

When trying to access the product controllers show view i'm getting the following error.

LoadError in ProductsController#show
Unable to autoload constant Role, expected /Users/tharindu/MyTasks/try2/mynewtask/app/models/role.rb to define it

Extracted source (around line #7):
5
6
7
8
9
10

    user ||= User.new # guest user (not logged in)

       if user.role == "admin"
         can :manage, :all, @products
       elsif user.role == "manager"
         can :read, Products, Delivery,Accounts

Please help me to solve this issue


Solution

  • The tutorial you are trying to implement doesn't has a seperate Role model and you are adding an association belongs_to :role. Instead you are saving the role in User table itself. So remove the association defined which should fix the issue.

    And currently the User would have one role you can also assign multiple roles to him as mentioned in the tutorial using a bitmask.

    But using any of the two methods you are not creating a seperate model so the association can't be defined instead you need to create instance methods. For seperate Role model refer this: https://github.com/ryanb/cancan/wiki/Separate-Role-Model