Rails教程第9章:重定向到错误的URL

时间:2014-01-01 05:56:10

标签: ruby-on-rails rspec ruby-on-rails-4 railstutorial.org

我在调试Rails教程的Rspec代码时遇到问题。当我运行我的rspec代码时,我收到此错误:

1) Authentication authorization as non-admin user submitting a DELETE request to the Users#destroy action
 Failure/Error: specify { expect(response).to redirect_to(root_url) }
   Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/signin>.
   Expected "http://www.example.com/" to be === "http://www.example.com/signin".
 # ./spec/requests/authentication_pages_spec.rb:106:in `block (5 levels) in <top (required)>'

2) Authentication authorization as wrong user submitting a GET request to the Users#edit action
 Failure/Error: specify { expect(response).to redirect_to(root_url) }
   Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/signin>.
   Expected "http://www.example.com/" to be === "http://www.example.com/signin".
 # ./spec/requests/authentication_pages_spec.rb:90:in `block (5 levels) in <top (required)>'

3) Authentication authorization as wrong user submitting a PATCH request to the Users#update action
 Failure/Error: specify { expect(response).to redirect_to(root_url) }
   Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/signin>.
   Expected "http://www.example.com/" to be === "http://www.example.com/signin".
 # ./spec/requests/authentication_pages_spec.rb:95:in `block (5 levels) in <top (required)>'

我的/spec/requests/authentication_pages_spec.rb的代码是:

require 'spec_helper'

describe "Authentication" do

  subject { page }

  describe "signin page" do
    before { visit signin_path }

    it { should have_content('Sign in') }
    it { should have_title('Sign in') }
  end

  describe "signin" do
    before { visit signin_path }

    describe "with invalid information" do
      before { click_button "Sign in" }

      it { should have_title('Sign in') }
      it { should have_error_message('Invalid') }

      describe "after visiting another page" do
        before { click_link "Home" }
        it { should_not have_error_message('Invalid') }
      end
    end

    describe "with valid information" do
      let(:user) { FactoryGirl.create(:user) }
      before { sign_in user }

      it { should have_title(user.name) }
      it { should have_link('Users',       href: users_path) }
      it { should have_link('Profile',     href: user_path(user)) }
      it { should have_link('Settings',    href: edit_user_path(user)) }
      it { should have_link('Sign out',    href: signout_path) }
      it { should_not have_link('Sign in', href: signin_path) }

      describe "followed by signout" do
        before { click_link "Sign out" }
        it { should have_link('Sign in') }
      end

    end
  end
  describe "authorization" do
    describe "for non-signed-in users" do
      let(:user) { FactoryGirl.create(:user) }

      describe "when attempting to visit a protected page" do
        before do
          visit edit_user_path(user)
          valid_signin(user)
        end

        describe "after signing in" do
          it "should render the desired protected page" do
            expect(page).to have_title('Edit user')
          end
        end
      end

      describe "in the Users controller" do

        describe "visiting the edit page" do
          before { visit edit_user_path(user) }
          it { should have_title('Sign in') }
        end

        describe "submitting to the update action" do
          before { patch user_path(user) }
          specify { expect(response).to redirect_to(signin_path) }
        end
        describe "visiting the user index" do
          before { visit users_path }
          it { should have_title('Sign in') }
        end
      end
    end
    describe "as wrong user" do
      let(:user) { FactoryGirl.create(:user) }
      let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
      before { sign_in user, no_capybara: true }

      describe "submitting a GET request to the Users#edit action" do
        before { get edit_user_path(wrong_user) }
        specify { expect(response.body).not_to match(full_title('Edit user')) }
        specify { expect(response).to redirect_to(root_url) }
      end

      describe "submitting a PATCH request to the Users#update action" do
        before { patch user_path(wrong_user) }
        specify { expect(response).to redirect_to(root_url) }
      end
    end
    describe "as non-admin user" do
      let(:user) { FactoryGirl.create(:user) }
      let(:non_admin) { FactoryGirl.create(:user) }

      before { sign_in non_admin, no_capybara: true }

      describe "submitting a DELETE request to the Users#destroy action" do
        before { delete user_path(user) }
        specify { expect(response).to redirect_to(root_url) }
      end
    end
  end
end

我的utilities.rb的代码是:

include ApplicationHelper

def valid_signin(user)
  fill_in "Email",    with: user.email
  fill_in "Password", with: user.password
  click_button "Sign in"
end

def sign_in(user, options={})
  if options[:no_capybara]
    # Sign in when not using Capybara.
    remember_token = User.new_remember_token
    cookies[:remember_token] = remember_token
    user.update_attribute(:remember_token, User.encrypt(remember_token))
  else
    visit signin_path
    fill_in "Email",    with: user.email
    fill_in "Password", with: user.password
    click_button "Sign in"
  end
end

def valid_user()
  fill_in "Name",         with: "Example User"
  fill_in "Email",        with: "user@example.com"
  fill_in "Password",     with: "foobar"
  fill_in "Confirmation", with: "foobar"
end

RSpec::Matchers.define :have_error_message do |message|
  match do |page|
    expect(page).to have_selector('div.alert.alert-error', text: message)
  end
end

当我运行rails服务器时,一切都运行良好。

有趣的是,当我在服务器上运行以及运行实际测试时,我的日志不同。在服务器上,以用户ID 2身份登录,我得到了:

Started GET "/users/1/edit" for 127.0.0.1 at 2013-12-31 21:28:31 -0800
Processing by UsersController#edit as HTML
  Parameters: {"id"=>"1"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 2]]
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "1"]]
Redirected to http://localhost:3000/
Filter chain halted as :correct_user rendered or redirected
Completed 302 Found in 4ms (ActiveRecord: 0.2ms)

在我的test.log文件中,我看到了:

Binary data inserted for `string` type on column `password_digest`
  [1m[35mSQL (0.4ms)[0m  INSERT INTO "users" ("created_at", "email", "name", "password_digest", "remember_token", "updated_at") VALUES (?, ?, ?, ?, ?, ?)  [["created_at", Sat, 28 Dec 2013 18:50:19 UTC +00:00], ["email", "michael@example.com"], ["name", "Michael Hartl"], ["password_digest", "$2a$04$qTOUv775ioIiAdufscqASuTZBoJEafqvDzc/.FGqmFR30NzQPalLa"], ["remember_token", "698696f7cfbefa641e2b87450b57499b056932ff"], ["updated_at", Sat, 28 Dec 2013 18:50:19 UTC +00:00]]
  [1m[36m (0.0ms)[0m  [1mRELEASE SAVEPOINT active_record_1[0m
Started GET "/users/1/edit" for 127.0.0.1 at 2013-12-28 10:50:19 -0800
Processing by UsersController#edit as HTML
  Parameters: {"id"=>"1"}
Redirected to http://www.example.com/signin
Filter chain halted as :signed_in_user rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)

编辑1:这是我的signed_in_user代码:

  private

    def user_params
      params.require(:user).permit(:admin, :name, :email, :password, :password_confirmation)
    end
    # Before filters

    def signed_in_user
      debugger
      unless signed_in?
        store_location
        redirect_to signin_url, notice: "Please sign in."
      end
    end

    def correct_user
      @user = User.find(params[:id])
      redirect_to root_path unless current_user?(@user)
    end

    def admin_user
      redirect_to root_path unless current_user.admin?
    end

    def strict_signed_in_user
      redirect_to root_url, notice: "You are already signed in." unless !signed_in?
    end

Edit2 :使用debugger我设法找到了一些错误:

F/Users/rasheedbustamam/Rails projects/sample_app/spec/support/utilities.rb:11
if options[:no_capybara]

[6, 15] in /Users/rasheedbustamam/Rails projects/sample_app/spec/support/utilities.rb
   6    click_button "Sign in"
   7  end
   8
   9  def sign_in(user, options={})
   10    debugger
=> 11    if options[:no_capybara]
   12      # Sign in when not using Capybara.
   13      remember_token = User.new_remember_token
   14      cookies[:remember_token] = remember_token
   15      user.update_attribute(:remember_token, User.encrypt(remember_token))
(rdb:1) v l
self = #<RSpec::Core::ExampleGroup::Nested_1::Nested_3::Nested_2::Nested_2:0x00000109aeb1b8>
options = {:no_capybara=>true}
remember_token = nil
user = #<User:0x00000109af02f8>

值得注意的是,remember_tokennil这似乎是一个问题。

提前非常感谢!

1 个答案:

答案 0 :(得分:1)

根据测试结果,您的signed_in_user过滤器会导致重定向,表明登录失败。我建议通过您的控制器代码跟踪登录执行和/或在此处共享相关代码以供审核。

更新:作为评论主题的后续行动,Hartl教程已经被成千上万的用户使用和验证,而迈克尔升级偶尔会出现新版本的缺陷,一般而言,它非常准确而且你如果你小心翼翼地跟着它会好的。你不能做的一件事是混合和匹配本教程各种版本的软件。