2013-09-24 97 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