Hartl的Ruby on Rails教程8.3注销错误

时间:2016-01-21 04:20:39

标签: ruby-on-rails

我在Michael Hartl的Ruby on Rails教程的8.3中的users_login_test中遇到了assert_select的问题。

这是测试:

test "login with valid information followed by logout" do
   get login_path
   post login_path, session: { email: @user.email, password: 'password' }
   assert is_logged_in?
   assert_redirected_to @user
   follow_redirect!
   assert_template 'users/show'
   assert_select "a[href=?]", login_path, count: 0
   assert_select "a[href=?]", logout_path
   assert_select "a[href=?]", user_path(@user)
   delete logout_path
   assert_not is_logged_in?
   assert_redirected_to root_url
   follow_redirect!
   assert_select "a[href=?]", login_path
   assert_select "a[href=?]", logout_path, count: 0
   assert_select "a[href=?]", user_path(@user), count: 0
end   

当我运行测试时,我得到1次失败:

FAIL["test_login_with_valid_information_followed_by_logout",    
UsersLoginTest, 2016-01-20 09:51:41 +0000]
test_login_with_valid_information_followed_by_logout#UsersLoginTest (1453283501.83s)
    Expected at least 1 element matching "a[href="/login"]", found 0..
    Expected 0 to be >= 1.
    test/integration/users_login_test.rb:31:in `block in <class:UsersLoginTest>'

这是我的会话控制器:

class SessionsController < ApplicationController
 def new
 end
def create
 user = User.find_by(email: params[:session][:email].downcase)
 if user && user.authenticate(params[:session][:password])
   log_in user
   remember user
   redirect_to user
 else
   flash.now[:danger] = 'Invalid email/password combination'
   render 'new'
 end
 end      

 def destroy
   log_out
   redirect_to root_url
 end
 end

我的sessions_controller有一个重定向到root_url的destroy方法。我不知道问题是什么,但我知道我的测试失败,当我尝试注销时,我被重定向到主页但我仍然登录(在角落里我仍然有我的个人资料,设置和注销的链接)。

@Papouche Guinslyzinho你让我发表意见,帮助并摧毁控制器:

查看:header.html.rb

      <header class="navbar navbar-fixed-top navbar-inverse">
        <div class="containter">
           <%= link_to "sample app", root_path, id: "logo" %>
          <nav>
            <ul class="nav navbar-nav navbar-right">
              <li><%= link_to "Home", root_path %></li>
              <li><%= link_to "Help", help_path %></li>
          <%if logged_in? %>
          <li><%= ;link_to "Users", "#"%></li>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Account <b class="caret"></b>
              </a>
              <ul class="dropdown-menu">
                <li><%= link_to "Profile", current_user %></li>
                <li><%= link_to "Settings", "#" %></li>
                <li class="divider"></li>
                <li> <%= link_to "Log out", logout_path, method: "delete" %> 
                </li>
              </ul>
          </li>
          <%else %>
          <li><%= link_to "Log in", login_path %></li>
          <%end %>
        </ul>
      </nav>
    </div>
  </header>

Sessions_helper:

module SessionsHelper

  #logs in given user
  def log_in(user)
    session[:user_id] = user.id
  end

  #Remembers user in session
  def remember(user)
    user.remember
    cookies.permanent.signed[:user_id] = user.id
    cookies.permanent[:remember_token] = user.remember_token
  end

  #returns the user corresponding to the remember token cookie
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
      elsif(user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  #returns true if the user is logged in, false otherwise
  def logged_in?
    !current_user.nil?
  end

  def log_out
      session.delete(:user_id)
      @current_user = nil
  end


  #forgets a persistent session
  def forget(user)
    user.forget
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
  end

  #logs out the current user
  def 
    forget(current_user)
    session.delete(:user_id)
    @current_user = nil
  end


end

Sessions_controller:destroy

 def destroy
    log_out
    redirect_to root_url
  end

2 个答案:

答案 0 :(得分:2)

首先尝试查看路线中是否有登录路径

rake routes | grep 'login'
你应该有这些:

login GET    /login(.:format)          sessions#new
      POST   /login(.:format)          sessions#create

然后你的错误:

Expected at least 1 element matching "a[href="/login"]", found 0..

这说它在你的html页面中找不到<a href="/login"...>。因此,启动rails服务器并转到浏览器并验证页面源,以查看登录的链接标记是否如下所示:<a href="/login"...>

enter image description here

答案 1 :(得分:1)

您正在引用Hartl教程的第8.3节,但看起来您已经开始研究下一部分Remember Me。这是您实现持久会话的地方。

我可以告诉你,因为你的代码中有一些'记住'的东西。例如:

def remember(user)
  user.remember
  cookies.permanent.signed[:user_id] = user.id
  cookies.permanent[:remember_token] = user.remember_token
end

您的测试失败了,因为您可能有一个活跃的记忆令牌Cookie,但您的log_out方法并没有“忘记”它。从本质上讲,你只完成了一半的Hartl部分;所以测试自然会失败(证明测试工作!)

如果您继续学习本教程,它将指导您在注销时忘记此cookie。或者,您可以回溯并删除8.3之后放置的位。无论哪种方式,这个测试都应该通过。