我正在关注Michael Hartl关于Ruby on Rails的优秀教程。我一直试图理解 ActionDispatch :: Response 的工作方式。这源自第9章的练习9(Rails版本3.2.3)。
特别要求我们确保 admin 用户无法自己User#destroy
。我知道如何做到这一点,但由于我正在尝试遵循TDD方法,我首先编写测试。
这是我测试中的相关摘录:
describe "authorization" do
describe "as non-admin user" do
let(:admin) {FactoryGirl.create(:admin)}
let(:non_admin) {FactoryGirl.create(:user)}
before{valid_signin non_admin}
describe "submitting a DELETE request to the Users#destroy action" do
before do
delete user_path(admin)
#puts response.message
puts response.succes?
end
specify{ response.should redirect_to(root_path) }
specify{ response.should_not be_success }
end
end
#Exercise 9.6-9 prevent admin from destroying himself
describe "as admin user" do
let(:admin){FactoryGirl.create(:admin)}
let(:non_admin){FactoryGirl.create(:user)}
before do
valid_signin admin
end
it "should be able to delete another user" do
expect { delete user_path(non_admin) }.to change(User, :count).by(-1)
end
describe "can destroy others" do
before do
puts admin.admin?
delete user_path(non_admin)
puts response.success?
end
#specify{response.should be_success}
specify{response.should_not be_redirect}
end
describe "cannot destroy himself" do
before do
delete user_path(admin)
puts response.success?
end
#specify{response.should_not be_success}
specify{response.should be_redirect}
end
end
.
.
.
end
除"can destroy others"
测试外,所有测试均通过。
但是,如果在puts response.success?
次请求后我delete
,我总是得到False
,因此没有任何请求“成功”。
手动与webapp交互并删除用户的工作正常,因此我认为response.success
并不意味着detroy
(或任何与此有关的请求)不成功,而是其他内容。我读到它与 HTTP响应200/302/400 之间的区别有关,但我不完全确定。
对于记录,这是我的User#destroy
:
def destroy
User.find(params[:id]).destroy
flash[:success]="User destroyed."
redirect_to users_path
end
对此有何看法? 谢谢!
修改
这是我的工厂:
FactoryGirl.define do
factory :user do
sequence(:name){ |n| "Person #{n}" }
sequence(:email){ |n| "person_#{n}@example.com"}
password "foobar"
password_confirmation "foobar"
factory :admin do
admin true
end
end
end
按照@Peter Alfvin的建议编辑2 ,我改变了行
let(:user){FactoryGirl.create(:user)}
到
let(:admin){FactoryGirl.create(:admin)}
一般来说,所有user
到admin
。我还在puts admin.admin?
请求之前添加了delete
。仍然没有工作!
编辑3
将测试"can destroy others"
更改为:
describe "can destroy others" do
before do
puts admin.admin?
delete user_path(non_admin)
puts response.success?
end
#specify{response.should be_success}
specify{response.should_not be_redirect}
end
似乎也没有帮助。
答案 0 :(得分:1)
对于您的“管理员”案例,您仍然以“常规”用户而非管理员用户身份创建和登录,这就是您无法销毁其他任何人的原因。
答案 1 :(得分:1)
response.success确实引用了HTTP响应代码。默认情况下,我相信这是200范围内的任何东西。 redirect_to在300范围内。
答案 2 :(得分:0)
确保您的用户工厂包含此行
factory :user do
#your user factory code
factory :admin do
admin true
end
end
然后FactoryGirl.create(:admin)
将返回管理员用户,或者您也可以使用user.toggle!(:admin)
将标准用户切换为管理员用户。
试试这个
describe "as admin user" do
let(:admin){FactoryGirl.create(:admin)}
let(:non_admin){FactoryGirl.create(:user)}
before do
valid_signin admin
end
it "should be able to delete another user" do
expect { delete user_path(non_admin) }.to change(User, :count).by(-1)
end
it "can destroy others" do #
before do
puts admin.admin?
delete user_path(non_admin)
puts response.success?
end
#specify{response.should be_success}
specify{response.should_not be_redirect}
end
it "cannot destroy himself" do
before do
delete user_path(admin)
puts response.success?
end
#specify{response.should_not be_success}
specify{response.should be_redirect}
end
end
describe创建一个魔术类,它从我的理解变成了描述类的一个子类。 Rails有很多这种魔力,它可能会让人感到困惑。此外,我还没有看到您的控制器,但是当您销毁用户时,您期望发生什么,因为如果您按照教程进行操作,那么通过浏览器发送的重定向delete
将调用您的destroy
方法教程中的UsersController
有这一行redirect_to users_url
所以response.should_not be_redirect
将始终失败,因为规范错误而不是控制器。