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

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

相关推荐
AMoon丶3 小时前
Golang--锁
linux·开发语言·数据结构·后端·算法·golang·mutex
白杆杆红伞伞3 小时前
Qt进程间通信
开发语言·qt
艾莉丝努力练剑3 小时前
确保多进程命名管道权限一致的方法
java·linux·运维·服务器·开发语言·网络·c++
2201_756206343 小时前
1111111
开发语言·python
一瓢西湖水3 小时前
CPU使用超过阈值分析
java·开发语言·jvm
特种加菲猫3 小时前
透过源码看本质:list 的模拟实现与核心原理
开发语言·c++
李日灐3 小时前
改造红黑树实现封装 map/set:感受C++ 标准容器的精妙设计与底层实现
开发语言·数据结构·c++·后端·算法·红黑树
故事和你913 小时前
sdut-程序设计基础Ⅰ-期末测试(重现)
大数据·开发语言·数据结构·c++·算法·蓝桥杯·图论
重庆兔巴哥3 小时前
如何在Dev-C++中使用MinGW-w64编译器?
linux·开发语言·c++
魔道不误砍柴功3 小时前
Java Function 高级使用技巧:从工程实战中来
java·开发语言·python