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

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

相关推荐
安妮的小熊呢7 小时前
CRMEB开源商城系统 & 标准版系统(PHP)开发规范
开发语言·javascript·php
子榆.7 小时前
CANN ATC编译器:模型从Python到达芬奇指令走了多远
开发语言·python·neo4j
Dontla7 小时前
Multi-Agent多智能体项目如何从MVP过渡到生产项目?
开发语言
兰令水8 小时前
topcode【随机算法题】【2026.5.20打卡-java版本】
java·开发语言·算法
我还记得那天8 小时前
C语言递归实现汉诺塔问题
c语言·开发语言
不吃土豆的马铃薯8 小时前
Spdlog 入门:日志记录器与日志槽基础详解
服务器·开发语言·c++·c·日志·spdlog
凯瑟琳.奥古斯特8 小时前
传输层核心功能解析
开发语言·网络·职场和发展
Fuyo_11198 小时前
C++中的活字印刷术——模板·初阶
开发语言·c++·笔记
在角落发呆8 小时前
跨越网络鸿沟:传统文件传输与现代内网穿透的奇妙交响
开发语言·php
Season4508 小时前
C++之模板元编程(前置知识 constexpr)
开发语言·c++