2013-09-24 2 views
0

Я следую превосходному руководству Майкла Хартла по Ruby on Rails. Я застрял, пытаясь понять путь ActionDispatch :: Response работает. Это происходит из упражнения 9 главы 9 (Rails версии 3.2.3).Rails response.should be_success никогда не бывает

В частности, нас просят убедиться, что пользователь 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 

Edit 2 как предложено @Peter Alfvin, я изменил строки

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

Решение моей проблемы можно найти в следующих статьях: http://stackoverflow.com/a/19013924/1338339 – lllllll

ответ

1

Для вашего случая с «администратором» вы все еще создаете и регистрируетесь как «обычный» пользователь, а не пользователь admin, поэтому вы не можете уничтожить кого-либо еще.

+0

Я думал, что это была проблема. Но я изменил его на ': admin', и он тоже не работает. См. Также мою фабрику, последнее редактирование. – lllllll

+1

Это связано с несколькими ошибками, вы часто не можете подтвердить существование какой-либо одной ошибки, исправив ее. :-) Если вы посмотрите на примеры в https://github.com/railstutorial/sample_app/blob/master/spec/controllers/users_controller_spec.rb, они подтвердят как этот ответ, так и комментарий в другом ответе от @AlexanderClark. 'redirect_to'. :-) –

+0

Я адаптировал код для Rails 3.2 (этот github этой версии не имеет ответа на это упражнение), используя 'expect {delete user_path (non_admin)}. Для изменения (: User,: count) .by (-1)' , но он терпит неудачу. Кажется, я не вижу других кратных ошибок. благодаря! – 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', удаляющий' non-admin', он должен * not * быть перенаправлением, правильно? См. Edit 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, который в учебнике имеет это line redirect_to users_url, так что response.should_not be_redirect всегда будет терпеть неудачу, потому что спецификация неверна, а не контроллер.

+0

У меня это уже есть! :) – lllllll

Смежные вопросы