用 CanCanCan 时遇到的一些情况

在使用 CanCanCan 做权限设计的时候,有几个地方需要注意。

当用户系统不止一个的时候

如果项目中的用户系统不止一个,比如说后台的系统用的是 admin,前台用的是 user;又如果后台的 admin 又分超级管理员和普通管理员,前台的 user 又分前台管理员、VIP、普通用户等,要利用 CanCanCan 做权限设计,就应该分开来设计。也就是说,分成 AdminAbilityUserAbility 来分别设置。

官方文档是用 rails g cancan:ability 来生成权限管理模型的,但是 rails g cancan:admin_ability 会报错。不过没关系,在 model 层手动新建一个admin_ability.rb就好。

比如说,这样。

class AdminAbility
  include CanCan::Ability

  def initialize(admin)
    admin ||= Administrator.new
    if admin.superadmin?
      can :manage, :all
    else
      can [ :edit, :update ], Administrator, id: admin.id
      can :read, Administrator
    end
  end

因为自定义了 ability 类,所以还需要改动另外一些默认设置,比如说 current_ability,默认的方法是这样的

def current_ability
  @current_ability ||= Ability.new(current_user)
end

也就是说,CanCanCan 的正常工作需要依赖两个默认值,一个是 Ability 类,另一个就是 current_user,所以这里需要把这个默认值覆盖掉,在相应的 Controller 里重定义 current_ability

def current_ability
  @current_ability ||= AdminAbility.new(current_admin)
end

这里 current_admin 是因为本来自定义了这个变量。

然后就可以在 controller 层或者 view 层使用 CanCanCan 的各种方法了。

当使用 rails-api 时

用类似的方法定义 user 的权限,总是提示找不到 authorize! 的方法。Google 之后,找到了原因:

If you’re using the rails-api gem, you’ll need to manually include the controller methods for CanCan

class ApplicationController < ActionController::API
  include CanCan::ControllerAdditions
end

因为这是一个小程序项目,去查 User 的 controller,果然是也是继承了 API,手动加上 CanCanCan 的 controller 方法就好了。

class API::V1::BaseController < ActionController::API
  include CanCan::ControllerAdditions
end
· rails