我在《Ruby on Rails 教程(第四版)》8.2.2 节中看到书上做了如下操作,但是我模仿着做了,但是没有效果
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
end
module SessionsHelper
# 登录指定用户
def log_in(user)
# 利用Rails提供的session方法在浏览器中创建一个临时cookie,内容是加密后的用户ID
# 后续请求中,可以使用session[:user_id]取回这个ID
session[:user_id] = user.id
end
end
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
respond_to do |format|
if user && user.authenticate(params[:session][:password])
# 保存用户登录信息
log_in user
# 用户登录成功,重定向到用户资料页面
format.html { redirect_to user }
else
# flash闪现消息在一个请求的生命周期内是持续存在的,但是重新渲染页面不算一次新的请求
# 因为使用flash.now代替(flash.now专门用于在重新渲染的页面中显示闪现消息)
flash.now[:danger] = "Log in failed, please check your email and password!"
format.html { render :new, status: :bad_request }
end
end
end
def destroy
end
end
module SessionsHelper
# 登录指定用户
def log_in(user)
# 利用Rails提供的session方法在浏览器中创建一个临时cookie,内容是加密后的用户ID
# 后续请求中,可以使用session[:user_id]取回这个ID
session[:user_id] = user.id
end
# 返回当前登录的用户(如果有的话)
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
# 判断用户是否已经登录,已登录返回true,否则返回false
def logged_in?
!@current_user.nil?
end
end
<% if logged_in? %>
<li class="nav-item">
<%= link_to "Users", '#', class: "nav-link" %>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Account
</a>
<ul class="dropdown-menu">
<li>
<%= link_to "Profile", user_path, class: "dropdown-item" %>
</li>
<li>
<%= link_to "Settings", '#', class: "dropdown-item" %>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<%= link_to "Log out", logout_path, method: "delete", class: "dropdown-item" %>
</li>
</ul>
</li>
<% else %>
<li class="nav-item">
<%= link_to "Log in", login_path, class: "nav-link" %>
</li>
<% end %>
我试了书上的操作,发现登录后用户看到的导航链接根本没有变(辅助方法current_user
和logged_in?
貌似没有起到作用),通过debugger
断点发现辅助方法中创建的@current_user对象
在转到用户资料页面后就是nil
了,所以用户登录后看到的链接不会变。
我改成了下面这样,效果是有了,但是我想知道书上之前那样写的操作为什么达不到效果。
<% if !session[:user_id].nil? %>
<li class="nav-item">
<%= link_to "Users", '#', class: "nav-link" %>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Account
</a>
<ul class="dropdown-menu">
<li>
<%= link_to "Profile", user_path, class: "dropdown-item" %>
</li>
<li>
<%= link_to "Settings", '#', class: "dropdown-item" %>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<%= link_to "Log out", logout_path, method: "delete", class: "dropdown-item" %>
</li>
</ul>
</li>
<% else %>
<li class="nav-item">
<%= link_to "Log in", login_path, class: "nav-link" %>
</li>
<% end %>
UsersController 控制器的 show 动作会处理用户资料页面的显示
class UsersController < ApplicationController
...
def show
@user = User.find(params[:id])
# .authenticate("123456")
end
...
end