如何在CanCanCan的can?方法中校验多个操作?
解决CanCanCan同时校验多个操作的问题
这个问题我之前也碰到过!CanCanCan的can?方法确实不直接支持一次性传入多个操作数组来校验,哪怕每个操作单独校验都返回true,数组形式调用can? [:destroy, :another_action], @project也会返回false——因为官方实现里并没有处理数组类型的操作参数。
不过我们可以自己封装一个简单的方法来实现这个需求,分两种常见场景:
场景1:需要所有操作都具备权限才返回true
如果要确保用户同时拥有所有传入的操作权限,可以在ApplicationHelper(供视图调用)或者ApplicationController(供控制器调用)里添加以下方法:
# 放在ApplicationHelper.rb里,视图和控制器都能调用(如果控制器要用到,记得加helper_method声明) def can_all?(actions, subject) # 遍历所有操作,确保每个操作的can?校验都通过 actions.all? { |action| can?(action, subject) } end
使用方式非常直观,直接替换原来的数组调用即可:
# 校验用户是否同时拥有destroy和another_action权限 can_all? [:destroy, :another_action], @project
场景2:只要有一个操作具备权限就返回true
如果需求是用户拥有任意一个传入的操作权限就返回true,可以封装另一个方法:
def can_any?(actions, subject) actions.any? { |action| can?(action, subject) } end
使用示例:
# 校验用户是否拥有destroy或another_action其中一个权限 can_any? [:destroy, :another_action], @project
额外提示:跨控制器和视图调用
如果想让这两个方法在控制器逻辑和视图模板中都能使用,推荐把方法写在ApplicationController里,再加上helper_method声明:
class ApplicationController < ActionController::Base helper_method :can_all?, :can_any? def can_all?(actions, subject) actions.all? { |action| can?(action, subject) } end def can_any?(actions, subject) actions.any? { |action| can?(action, subject) } end end
这样不管是在控制器里做权限判断,还是在视图里控制元素显示,都能方便地批量校验权限啦。
内容的提问来源于stack exchange,提问作者NateW
相关产品推荐
相关产品推荐

