cancan 笔记Created at 9 months ago |
https://github.com/ryanb/cancan
gem “cancan”
权限定义在类 Ability 中,放在 model,安装之后生成
rails g cancan:ability
CanCan 的权限定义的上下文可以使用这5个元素:动作(action),主题类,主题类的实例,用户实例,条件判断语句。
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
:manage,:read 称为权限的 action,内置对 REST 7 种 action 的支持,也可以随意定义 action,其实就是一个符号。
can :read, Project, :active => true, :user_id => user.id
user 可以阅读 active 为 true,user_id 等于 user.id 的 project。
附:在 controller 中,可以用 projects = Project.accessible_by(current_ability)
获取当前用户允许阅读(:read)的 project。这个便捷方法称为 Fetching Records。
如果权限非常复杂,可以使用 block 作为条件。当 block 返回 ture 时权限通过,否则拒绝。
can :update, Project do |project|
project.priority < 3
end
更直接地定义权限,更复杂的定义可以用这种方式。但基本上用例三的 Block 就足够了。
can do |action, subject_class, subject|
# ...
end
在 controller 和 view 中可以使用 can? 和 cannot? 方法判断用户对资源的访问权。
例:
controller:
can? :destroy, @project
cannot? :destroy, @project
view:
<% if can? :create, Project %>
<%= link_to "New Project", new_project_path %>
<% end %>
注意:如果权限定义使用了条件判断,那么对类的权限检查总会返回 true
can :read, Project, :priority => 3
can? :read, Project # returns true
与 can? cannot? 的区别是授权失败时候会抛出 CanCan::AccessDenied 异常,可以通过在 ApplicationController.rb 里面用 捕获
in controller :
authorize! :read, Article, :message => "Unable to read this article."
in application_controller:
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
假设 user 有 role? 方法
# in Ability#initialize if user.role? :moderator can :manage, Post end if user.role? :admin can :manage, Thread end if user.role? :superadmin can :manage, Forum end