0

这是我想做的事情:

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

有任何想法吗?

4

1 回答 1

1

预期行为

为了能够使用 and 的块语法#can#cannot您必须首先在控制器中加载资源。正如医生所说

仅当存在实际实例对象时才评估该块。在检查类的权限时(例如在 index 操作中),它不会被评估。这意味着任何不依赖于对象属性的条件都应该移到块之外。

要让这个实例对象出现,你需要让 cancan 加载它:

class UsersController < ApplicationController
  load_and_authorize_resource
end

这将@user在您的控制器和传递给#cannot. 现在有一个问题。

...在 rails-4 上中断(截至 2013 年 10 月 2 日)

CanCan 有 rails-4 的问题:它不处理 StrongParameters。这会导致自动资源加载崩溃#create#update操作。这是一个正在运行的问题,Ryan 承诺为 cancan-2 提供解决方案(似乎已为 cancan-1 放弃)。

无论如何,您可以使用此 PR 中的代码使 cancan 兼容强参数。在这里,它被提取到一个猴子补丁中。我更喜欢使用猴子补丁而不是将 gem 指向特定的提交或分叉,这样我就不会丢失任何主 gem 更新。

备用资源加载

再次阅读文档,我找到了另一种避免强参数问题的方法。如果在 #load_resource 之前使用 before_filter ,则可以重载加载器。

有几个含义:

  • 您必须自己实现逻辑才能在#new, #show,#create等之间产生差异(可以使用多个条件过滤器)
  • 您必须自己分配参数(因此,您可以正确使用强参数)

#can这破坏了 cancan 资源加载的简单性,并且唯一的目的是让 cancan 在您想使用带有and的块时知道资源是什么#cannot

我仍然宁愿使用猴子补丁,这样当上游修复问题时,你就不会在控制器中留下很多无用的代码。

于 2013-10-02T08:28:36.923 回答