2013-09-24 30 views
0

我正在关注Michael Hartl关于Ruby on Rails的优秀教程。我卡住试图了解的方式ActionDispatch :: Response的作品。这源自第9章的练习9(Rails版本3.2.3)。Rails response.should be_success永远不是真的

特别是我们被要求确保用户自己无法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 

编辑2通过@Peter Alfvin的建议,我改线

let(:user){FactoryGirl.create(:user)} 

let(:admin){FactoryGirl.create(:admin)} 

以及全部useradmin。我还在delete请求之前添加了一个puts admin.admin?。还是行不通!

编辑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

我的问题的解决方案可以在后续的这里找到:http://stackoverflow.com/a/19013924/1338339 – lllllll

回答

1

对于您的“管理员”情况,您仍然以“常规”用户而不是管理员用户的身份创建和登录,这就是为什么您不能销毁其他人。

+0

我认为这是问题。但是我把它改成了':admin',但它也不起作用。另见我的工厂,上次编辑。 – lllllll

+1

这是关于出现多个错误的问题,您通常无法通过修复它来确认是否存在任何错误。 :-)如果你看看https://github.com/railstutorial/sample_app/blob/master/spec/controllers/users_controller_spec.rb中的例子,他们确认了这个答案和@AlexanderClark的其他答案中的评论。 'redirect_to'。 :-) –

+0

我使用'expect {delete user_path(non_admin)}。改变(:User,:count).by(-1)'来修改Rails 3.2的代码(这个版本的github没有回答这个练习) ,但它失败了。我似乎无法发现其他多个错误。谢谢! – lllllll

1

response.success确实引用了HTTP响应代码。默认情况下,我相信这是200范围内的任何内容。redirect_to在300范围内。

+0

那么,这是否意味着我不应该不是那样测试吗? – lllllll

+1

是的。如果动作重定向,则'response.should redirect_to'代替'response.should be_success'。你可以说'response.should be_redirect',但如果你也测试'redirect_to' –

+0

似乎检查'response.should_not be_redirect'失败,那将是多余的。而且,考虑到这是一个'admin'删除一个'非管理员',它应该*不*是一个重定向,对吧?参见编辑3 – lllllll

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 

描述创建一个魔术类成为从我的理解描述类的子类。 Rails有很多这样的魔法,它可能会让人困惑。另外我还没有看到你的控制器,但是当你摧毁一个用户时你期望发生什么,因为如果你遵循教程,那么将会有一个重定向delete通过浏览器发送将调用你的destroy方法UsersController在教程中有这个行redirect_to users_url所以response.should_not be_redirect将总是失败,因为规范是错误的不是控制器。

+0

我已经得到了! :) – lllllll