どうも!chuckです。8章の学習が終わりましたのでメモ。
8章 サインイン、サインアウト
ここまではサインインが失敗した場合を実装しました。ここからはサインインが成功する場合を実装していきます。
Sign_in関数をつくろう
なにはともあれ、Sign_in関数を完成させます。ここでの目標はユーザの登録が完了して、プロフィールページへとリダイレクトされることです。
サインイン関数は、新しくモジュールを作成する手もありますが、ここではSessionHelperを使います。なぜならばサインイン関数はビューとコントローラから参照される必要があるからです。
Helperならばビューから無条件で使えますし、コントローラとの連携もincludeの記述を追加するだけで済みます。
ユーザ情報の保持の仕方
HTTPリクエストは基本的にはステートレスです。つまりセッションが保持されません。ここではCookieに情報を保持させることにします。これならばCookieを参照することでページをまたいでもユーザを追跡することができます。
記憶トークン
そこで登場するのが記憶トークンです。この記憶トークンにサインインしたユーザの情報を保持させます。
このSessionオブジェクトがCookieにユーザーIDを追加してくれます。
また、記憶トークンとユーザを関連付けるためにモデルに変更を加えます。
一方、実際のコマンドはこちら。
addでレコードを追加するんですね。
モデルを変更したので、おなじみのモデル更新コマンド。
さらに、記憶トークンを検索できるようにindexを振っておきます。
ユーザ認証の方向性
さて、これでモデルの準備が整いました。
ここでは記憶トークンにはSecureRandomモジュールの持つurlsafe_base64メソッドを利用することにします。これは長さ16の英数字ランダム文字列を返します。
認証の方向性としては、ブラウザにこのbase64トークンを保存しておき、DBにはトークンを暗号化したものを保存しておきます。そしてCookieからトークンを読みだして、暗号化してDB上のものと照会します。これでユーザを自動的にサインインさせます。
記憶トークンのテスト
まずテストユーザーを保存して、そのユーザの記憶トークンが空でないことを確認します。
ここで、before_createというコールバックを利用する。
create_remember_tokenはメソッド参照というもので、同名のメソッドを探してくれる。
こちらがそのメソッド。まずランダム文字列を作って暗号化、そしてユーザーの属性の一つに要素代入をしている。selfを使っているのがそれにあたり、これがないと新しくローカル変数が作られてしまう。
これらを最終的にユーザーモデルに記述したのがこちら。
冒頭のbefore_createを忘れないようにしたい。
Sign_inメソッドの実装
いよいよSign_inメソッドの実装です。
こちらがSign_in関数
def sign_in(user)の中身を1行ずつ見ていくと、
1, トークンを新規作成。
2, 暗号化されていないトークンをブラウザのCookieに保存。
3, 暗号化されたトークンをDBに保存。
4, 与えられたユーザーを現在のユーザーに設定。
といった感じ。うん、流れはわかるけど、新規要素多すぎ…(ヽ´ω`)笑
さて、ここで未実装なのがcurrent_user。これを実装していく。
current_userはビューからもコントローラからもアクセスできる必要がある。
そうすることで以下の構文を使用できるようになる。(そうなんだ)
ちなみに、ここでもcurrent_userへは要素代入する必要がある。
そのための記述がこちら。
(なんだこれは…)
remember_tokenを使用して現在のユーザを検索するための、最終的なコード。
| |=とかいう変な論理演算子が見えるけど、きっと気のせいだろう。今はスルーしよう(ヽ´ω`)
レイアウト変更
サインインの状態に応じてレイアウトを変更します。
埋め込みRubyのif-elseを利用する。
なので、signed_in?論理値を定義する必要がある。
ユーザーがサインインしている状態とはつまり、セッションに現在のユーザがいることで表せる。(current_user != nil)
また、この後、サインアップ(登録)した後にも個別のプロフィールページに飛ぶように設定。
以上でサインイン、サインアウト機能は完成ですヽ(=´▽`=)ノ
次回は9章 ユーザーの更新・表示・削除です。