灵感来自这里https://github.com/kristianmandrup/cantango/wiki/CanCan-vs-CanTango
如果权限不多,我们可以通过这种方式来定义
ruby
class CanCan::Ability
def initialize user, options = {}
if !user
can :read, :all
end
if user
admin_rules if user.roles.include? :admin
editor_rules if user.roles.include? :editor
default_rules
end
end
def admin_rules
can :manage, :all
end
def editor_rules
can :manage, [Article, Post]
end
end
改的灵活点
ruby
class CanCan::Ability
def initialize user, options = {}
user ? user_rules : guest_user_rules
end
def user_rules
user.roles.each do |role|
exec_role_rules(role) if user.roles.include? role
end
default_rules
end
def exec_role_rules role
meth = :"#{role}_rules"
send(meth) if respond_to? meth
end
# various rules methods for each role
def admin_rules
can :manage, :all
end
def editor_rules
can :manage, [Article, Post]
end
...
def default_rules
can :read, :all
end
end
上面是原文出处,实际使用的时候还是不方便,我改成这样了(非一比一还原)。使用define_method 定义那个每个方法:
ruby
class Ability
include CanCan::Ability
@@permissions = xxx
def initialize(user)
@user= user|| User.new
@user.roles.each do |role|
exec_role_rules(role) if @user.has_role?(role)
end
end
Role.all.each do |role|
define_method "rules_#{role.name.gsub(" ", "_")}" do
role_permissions = RolePermission.where(role_id: role.id)
unless role_permissions.blank?
role_permissions.each do |rp|
permission_value = @@permissions[rp.permission_key]
entities = permission_value["entities"].map{|e| e.constantize}
actions = permission_value["actions"].map{|e| e.to_sym}
can actions, entities
end
end
end
end
def exec_role_rules(role)
meth = :"rules_#{role.name.gsub(" ", "_")}"
send(meth) if respond_to? meth
end
end
经测试嘎嘎好用,就是我还需要添加一些条件筛选,导致我这个不能用,得删掉,有点可惜,记录一下~