一. Sessions 控制器
登录和退出功能由 Sessions 控制器中相应的 REST 动作处理 : 登录表单在 new 动作中处理, 登录的过程是向 create 动作发送 POST 请求, 退出则是向 destroy 动作发送 DELETE 请求。
1.首先生成 Sessions 控制器, 以及其中的 new 动作:
$ rails generate controller Sessions new
Users 资源使用特殊的 resources 方法自动获得 REST 式路由, 而 Sessions 资源则只能使用具名路由, 处理发给 /login 地址的 GET 和 POST 请求, 以及发给 /logout 地址的 DELETE 请求, 如下图所示(删除了 rails generate controller 生成的无用路由)。
(1).添加一个资源, 获得会话的标准 REST 式动作 RED
打开文件:config/routes.rb
添加上图中的路由规则之后, 还要创建Session时生成的测试, 使用新的登录路由, 如下图所示:
(2).更新 Sessions 控制器的测试, 使用新的登录路由 GREEN
打开文件:test/controllers/sessions_controller_test.rb
Sessions 资源的路由规则会把 URL 和动作对应起来, 如下图所示:
至此, 我们添加了好几个自定义的具名路由, 现在最好看一下完整的路由列表。我们可以执行 rails routes 命令生成路由列表:
注:你没必要完全理解输出的这些路由。像这样查看路由能对应用支持的动作有个整体认识。
二. 登录表单
登录表单和注册表单之间的主要区别是, 会话不是模型, 因此不能创建类似 @user 的变量。所以, 构建登录表单时, 我们要为 form_for 稍微多提供一些信息。form_for(@user)的作用是让表单向 /users 发起 POST 请求。对会话来说, 我们需要指明资源的名称以及相应的 URL:form_for(:session, url: login_path)知道怎么调用 form_for 之后, 参照注册表单编写登陆表单, 如图所示:
1.登录表单的代码
打开文件:app/views/sessions/new.html.erb
注:为了操作方便, 我们还加入了指向“注册”页面的链接。(导航栏中的“Login”还没填写地址,所以你要在地址栏中输入 /login。稍后会修正这个问题。)
2.页面
三. 查找并验证用户的身份
首先,我们要为 Sessions 控制器编写一个最简单的 create 动作, 以及空的 new 动作和 destroy 动作, 如下图所示:
1.Sessions 控制器中 create 动作的初始版本
打开文件:app/controllers/sessions_controller.rb
create 动作现在只渲染 new 视图, 不过这为后续工作做好了准备。提交 /login 页面中的表单后, 显示的页面如下图所示:
2.查找并验证用户的身份
打开文件:app/controllers/sessions_controller.rb
上图中红框内的第一行使用提交的电子邮件地址从数据库中取出相应的用户。(我们前面说过, 电子邮件地址都是以小写字母形式保存的, 所以这里调用了 downcase 方法, 确保提交有效的地址后能查到相应的记录。)高亮显示的第二行看起来很怪, 但在 Rails 中经常使用:
user && user.authenticate(params[:session][:password])
我们使用 && (逻辑与)检测获取的用户是否有效。因为除了 nil 和 false 之外的所有对象都被视作真值, 所以上面这个语句可能出现的结果如下表所示。从表中可以看出, 当且仅当数据库中存在提交的电子邮件地址, 而且对应的密码和提交的密码匹配时, 这个语句才会返回 true 。
3.渲染闪现消息
布局中已经加入了显示闪现消息的局部视图, 所以无需其他修改, flash[:danger] 消息就能显示出来; 而且因为使用了 Bootstrap 提供的 CSS, 消息的样式也很美观,如图所示::
注:就跟代码中标注的一样, 现在的闪现消息有问题问题在于, 闪现消息在一个请求的生命周期内是持续存在的, 而重新渲染页面(使用 render 方法)与重定向不同, 不算是一次新请求, 所以你会发现这个闪现消息存在的时间比预期的要长很多。
例如:提交无效的登录信息, 然后访问首页, 还会显示这个闪现消息:
4.测试闪现消息
首先, 为应用的登录功能生成一个集成测试文件:
$ rails generate integration_test users_login
(1).捕获继续显示闪现消息的测试 RED
打开文件:test/integration/users_login_test.rb