Ruby CanCanCan 动态定义方法

灵感来自这里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

经测试嘎嘎好用,就是我还需要添加一些条件筛选,导致我这个不能用,得删掉,有点可惜,记录一下~

相关推荐
siy233316 分钟前
[c语言日记] 数组的一种死法和两种用法
c语言·开发语言·笔记·学习·链表
njxiejing34 分钟前
Python NumPy安装、导入与入门
开发语言·python·numpy
Rhys..1 小时前
Python&Flask 使用 DBUtils 创建通用连接池
开发语言·python·mysql
土了个豆子的1 小时前
04.事件中心模块
开发语言·前端·visualstudio·单例模式·c#
@菜菜_达1 小时前
Lodash方法总结
开发语言·前端·javascript
GISer_Jing2 小时前
低代码拖拽实现与bpmn-js详解
开发语言·javascript·低代码
@areok@2 小时前
C++mat传入C#OpencvCSharp的mat
开发语言·c++·opencv·c#
小王C语言2 小时前
【C++进阶】---- map和set的使用
开发语言·c++
Elnaij2 小时前
从C++开始的编程生活(8)——内部类、匿名对象、对象拷贝时的编译器优化和内存管理
开发语言·c++
yb0os13 小时前
RPC实战和核心原理学习(一)----基础
java·开发语言·网络·数据结构·学习·计算机·rpc