Rails response.should be_success is never true

不问归期 提交于 2019-12-13 06:42:02

问题


I am following Michael Hartl's excellent tutorial on Ruby on Rails. I'm stuck trying to understand the way ActionDispatch::Response works. This derives from Exercise 9 of Chapter 9 (Rails version 3.2.3).

In particular we're asked to make sure that the admin user is unable to User#destroy himself. I have an idea how to do that, but since I'm trying to follow a TDD methodology, I'm first writing the tests.

This is the relevant snippet in my test:

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

All the tests pass except the "can destroy others" test.

However, if I puts response.success? after every delete request, I always get False, so none of the requests "succeed".

Manually interacting with the webapp and deleting users works just fine, so I assume that response.success does not mean that the detroy(or whatever request for that matter) was not successful, but something else. I read it has to do with the difference between HTTP responses 200/302/400, but I'm not totally sure.

For the record, this is my User#destroy:

def destroy
    User.find(params[:id]).destroy
    flash[:success]="User destroyed."
    redirect_to users_path
end

Any light on this? thanks!

Edit

This is my factory:

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 as suggested by @Peter Alfvin, I changed lines

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

to

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

And all user to admin in general. I also added a puts admin.admin? before the delete request. Still not working!

Edit 3

Changing the test "can destroy others" as:

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

Does not seem to help either.


回答1:


For your "admin" case, you're still creating and logging in as a "regular" user instead of an admin user, which is why you can't destroy anyone else.




回答2:


response.success does indeed refer to the HTTP response code. By default, I believe this is anything in the 200 range. redirect_to is in the 300 range.




回答3:


Make sure your user Factory includes this line

factory :user do
  #your user factory code
  factory :admin do 
    admin true
  end
end

Then FactoryGirl.create(:admin) will return an admin user or you can also use user.toggle!(:admin) which will switch a standard user to an admin user.

try this then

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 creates a magic Class it becomes a subClass of the describe class from my understanding. Rails has a lot of this magic and it can get confusing. Also I have not seen your controller but what are you expecting to happen when you destroy a user because if you followed the tutorial then there will be a redirect delete sent through the browser will call your destroy method in the UsersController which in the tutorial has this line redirect_to users_url so response.should_not be_redirect will always fail because the spec is wrong not the controller.



来源:https://stackoverflow.com/questions/18990403/rails-response-should-be-success-is-never-true

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!