这是我想要做的:
分配了User
角色的admin
无法更新User
角色god
的角色。所以这就是我提出的代码:
if user.has_role? 'admin'
can :manage, :all
cannot :update, User do |resource|
resource.has_role?('god')
end
end
但是,resource
似乎总是返回nil
。
有什么想法吗?
答案 0 :(得分:1)
为了能够使用#can
和#cannot
的块语法,您必须首先在控制器中加载资源。 As doc says:
当实际的实例对象是时,仅评估该块 当下。检查类的权限时不会对其进行评估 (例如在索引动作中)。这意味着任何条件都没有 依赖于对象的属性应该移到外面 块。
要使此实例对象存在,您需要让cancan加载它:
class UsersController < ApplicationController
load_and_authorize_resource
end
这会使您的控制器和传递给@user
的块中的#cannot
可用。现在有一个问题。
CanCan有一个rails-4的问题:它不处理StrongParameters。这会导致自动资源加载在#create
和#update
操作中崩溃。这是a running issue,Ryan承诺为cancan-2提供解决方案(似乎放弃了cancan-1)。
无论如何,您可以使用此PR中的代码使cancan与强参数兼容。这是在a monkey patch中提取的。我更喜欢使用猴子补丁而不是将gem指向特定的提交或分叉,这样我就不会丢失任何主宝石更新。
再次阅读文档,我发现了另一种避免强参数问题的方法。你可以overload loader if you use a before_filter before #load_resource。
有几个含义:
#new
,#show
,#create
等之间产生差异(可能会使用多个条件过滤器)这会破坏cancan资源加载的简单性,并且其唯一目的是让cancan知道当您想要使用#can
和#cannot
的块时资源是什么。
我还是宁愿选择猴子补丁,这样当问题在上游修复时,你的控制器中就不会有很多无用的代码了。