I am using Rails 4 with Devise and CanCanCan, and for some reason when I try to give users CRUD permissions only for products that they have made, none of the CanCanCan permission settings go through and users can only do read only. However, the moderator and admin permissions work as intended.
ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.is? :admin
can :manage, :all
elsif user.is? :moderator
can :read, :all
can :manage, @products
elsif user.is? :user
can :read, :all
can :create, :all
can :manage, @products do |product|
product.try(:user) == user
end
else
can :read, :all
end
end
end
user.rb
has_many :products
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
before_save :assign_role
Roles = [ :admin , :moderator , :user ]
def is?( requested_role )
self.role == requested_role.to_s
end
def assign_role
self.role = Role.find_by role: "user" if self.role.nil?
end
.html file
<% if can? :update, @products %>
<%= link_to "Edit", edit_product_path(@product) %>
<% end %>
<% if can? :destroy, @products %>
<%= link_to "Delete", product_path(@product), method: :delete, data: { confirm: "Are you sure?"} %>
<% end %>
controller
class ProductsController < ApplicationController
respond_to :html, :json
load_and_authorize_resource
def create
@product = current_user.products.build(product_params)
@product.user_id = current_user.id
if @product.save
redirect_to products_path
else
render 'new'
end
end
def product_params
params.require(:product).permit(:product_name, :product_description, :user_id)
end
EDIT:
users SQL table
+------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| email | varchar(255) | NO | UNI | | |
| encrypted_password | varchar(255) | NO | | | |
| reset_password_token | varchar(255) | YES | UNI | NULL | |
| reset_password_sent_at | datetime | YES | | NULL | |
| remember_created_at | datetime | YES | | NULL | |
| sign_in_count | int(11) | NO | | 0 | |
| current_sign_in_at | datetime | YES | | NULL | |
| last_sign_in_at | datetime | YES | | NULL | |
| current_sign_in_ip | varchar(255) | YES | | NULL | |
| last_sign_in_ip | varchar(255) | YES | | NULL | |
| role | varchar(255) | YES | | NULL | |
+------------------------+--------------+------+-----+---------+----------------+
products SQL table
+-----------------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| project_goal | int(11) | YES | | NULL | |
| product_name | varchar(255) | YES | | NULL | |
| product_description | varchar(255) | YES | | NULL | |
| project_category | varchar(255) | YES | | NULL | |
...
| expiration_date | datetime | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| user_id | int(11) | YES | | NULL | |
+-----------------------------------+--------------+------+-----+---------+----------------+
And here is my file structure