1
votes

Okay, so I am trying to create a user role system into my project using a combination of Devise and CanCan. I know that this is a popular combination but after working through a half dozen half-completed tutorials I finally got something working, but am still having a problem.

Here's a description: Users can register and they can be either an Administrator, Worker, or Client. The option that they choose saves to the database as it should, but the problem comes in when I try to use these options in CanCan. Here's my code so you can see what I have so far:

user.rb

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, 
                  :subdomain, :first_name, :last_name

  validates_presence_of :email
  validates_uniqueness_of :email, :case_sensitive => false

  ROLES = %w[admin worker client]

  def role?(role)
    roles.include? role.to_s
  end
end

role.rb

class Role < ActiveRecord::Base
  has_many :assignments
  has_many :users, :through => :assignments
end

assignment.rb

class Assignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
end

ability.rb (this is for CanCan)

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new #guest user

    if user.role? :admin
      can :manage, :all
    else
      can :read, :all
    end

    if user.role?(:worker)
      can :create, Project
      can :update, Project do |project|
        project.try(:user) == user
      end
    end
  end
end

project.rb

class Project < ActiveRecord::Base
    has_many :lists, :dependent => :destroy
    has_many :messages, :dependent => :destroy
    belongs_to :user

    attr_accessible :title, :description
    validates :title,           :presence => true,
                                :length => { :minimum => 5 }
end

Those are all of my models. I have followed the tutorial here: http://railscasts.com/episodes/192-authorization-with-cancan and made sure my code was the same, albeit changing the user roles, but I keep getting the same error:

Rails error with CanCan

I have load_and_authorize_resource in my projects controller and in my projects view I have:

<% if can? :edit, @project %>
    <td><%= link_to 'Edit', edit_project_path(project) %></td>
<% end %>

Nothing's working right now. This is kind of urgent and I'm not all that experienced in Rails so I would be very grateful for any help or suggestions that any of you have. Let me know if you need to see any more of my code or would like to describe more what I am trying to accomplish. Thanks!

1
3 things, First, in your user model try replacing roles.include? role.to_s with self.roles.include? role.to_s. Second, are your gems up to date? make sure you're using the latest versions and maybe just run bundle update. Third, I would suggest adding the rolify gem to the devise and cancan combo if you have time to refactor, because it's awesome. - n_i_c_k

1 Answers

2
votes

You are missing the relationship between Users and Roles :)

On your user.rb

has_many :assignments
has_many :roles, :through => :assignments

And then user.roles will be define ;)