问题描述
|
我(最后)将CanCan / Ability连接到我的应用程序中,并且我首先编写了RSpec测试。但是他们失败了-我的能力似乎过于宽容,我不明白为什么。
首先是能力类。目的是非管理员用户只能自己管理。特别是,他们不能查看其他用户:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # create guest user if needed
if (user.has_role?(:admin))
can(:manage,:all)
else
can(:manage,User,:id => user.id)
end
end
end
RSpec测试:
require \'spec_helper\'
require \'cancan/matchers\'
describe Ability do
before(:each) do
@user = User.create
end
describe \'guest user\' do
before(:each) do
@guest = nil
@ability = Ability.new(@guest)
end
it \"should_not list other users\" do
@ability.should_not be_able_to(:read,User)
end
it \"should_not show other user\" do
@ability.should_not be_able_to(:read,@user)
end
it \"should_not create other user\" do
@ability.should_not be_able_to(:create,User)
end
it \"should_not update other user\" do
@ability.should_not be_able_to(:update,@user)
end
it \"should_not destroy other user\" do
@ability.should_not be_able_to(:destroy,@user)
end
end
end
所有这五个测试均失败。我已经阅读了Ryan的文档部分,他说:
重要提示:如果
存在条件将被忽略
在上课时,它将
返回true。
...但是最多只能解释五个失败中的两个。很明显,我缺少基本的东西。
解决方法
我希望这可以工作:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # create guest user if needed
if (user.has_role?(:admin))
can(:manage,:all)
elsif user.persisted?
can(:manage,User,:id => user.id)
end
end
end
我不确定如果通过:id => nil
,行为将被定义为什么,这在来宾情况下会发生,但是无论如何,如果您不希望来宾访问列表视图,则您不应该\根本不给那个用户打can :manage,User
。
总的来说,我发现分配ѭ5使得能力难以推理。
,嘿,显然这应该可行,但是一些重构可以帮助您发现问题:
require \'spec_helper\'
require \'cancan/matchers\'
describe Ability do
before(:each) { @user = User.create }
describe \'guest user\' do
before(:each) { @ability = Ability.new(nil) }
subject { @ability } # take advantage of subject
it \"should not be an admin user\" do
@user.should_not be_admin
@user.should be_guest
end
it \"should_not show other user\" do
should_not be_able_to(:read,@user)
end
it \"should_not create other user\" do
should_not be_able_to(:create,User)
end
it \"should_not update other user\" do
should_not be_able_to(:update,@user)
end
it \"should_not destroy other user\" do
should_not be_able_to(:destroy,@user)
end
end
end
请注意,我也删除了示例“ 7”。
希望对您有帮助。
,我已经习惯了回答自己的问题,但是我给@jpemberthy和@Austin Taylor指出了正确的方向。首先(这是装饰性的),我将其添加到我的用户模型中:
class User
...
def self.create_guest
self.new
end
def guest?
uninitialized?
end
end
并相应地清理了我的能力模型:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.create_guest
if (user.admin?)
<admin abilities here>
elsif (user.guest?)
<guest abilities here>
else
<regular user abilities here>
end
end
end
但是真正的解决方法是在我的RSpec测试中。由于用户对电子邮件和密码字段进行了验证,因此我的原始代码为:
before(:each) do
@user = User.create
end
失败,因此创建了未初始化的ѭ11。由于:id字段为nil,因此Ability子句:
can(:manage,:id => user.id)
来宾用户成功,因为nil == nil(如果有意义)。添加必填字段以满足用户验证(几乎)使所有工作正常。
道德:正如@jpemberthy在他的代码中建议的那样,请始终进行测试以确保您的用户对象具有应有的特权! (我还有另一个关于CanCan的问题,希望它的头脑比这个更少,出现在您附近的StackOverflow主题中……)